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;
219 virtual std::optional<CPubKey> GetRootPubKey()
const = 0;
221 virtual std::optional<CExtPubKey> GetRootExtPubKey()
const = 0;
224 virtual std::unique_ptr<PubkeyProvider> Clone()
const = 0;
227 virtual bool IsBIP32()
const = 0;
230class OriginPubkeyProvider final :
public PubkeyProvider
233 std::unique_ptr<PubkeyProvider> m_provider;
236 std::string OriginString(StringType type,
bool normalized=
false)
const
239 bool use_apostrophe = (!normalized && m_apostrophe) || type == StringType::COMPAT;
244 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) {}
247 std::optional<CPubKey> pub = m_provider->GetPubKey(pos, arg,
out, read_cache, write_cache);
248 if (!pub)
return std::nullopt;
249 Assert(
out.pubkeys.contains(pub->GetID()));
250 auto& [pubkey, suborigin] =
out.origins[pub->GetID()];
252 std::copy(std::begin(m_origin.fingerprint), std::end(m_origin.fingerprint), suborigin.fingerprint);
253 suborigin.path.insert(suborigin.path.begin(), m_origin.path.begin(), m_origin.path.end());
256 bool IsRange()
const override {
return m_provider->IsRange(); }
257 size_t GetSize()
const override {
return m_provider->GetSize(); }
258 bool IsBIP32()
const override {
return m_provider->IsBIP32(); }
259 std::string
ToString(StringType type)
const override {
return "[" + OriginString(type) +
"]" + m_provider->ToString(type); }
263 if (!m_provider->ToPrivateString(arg, sub))
return false;
264 ret =
"[" + OriginString(StringType::PUBLIC) +
"]" + std::move(sub);
270 if (!m_provider->ToNormalizedString(arg, sub, cache))
return false;
276 ret =
"[" + OriginString(StringType::PUBLIC,
true) + std::move(sub);
278 ret =
"[" + OriginString(StringType::PUBLIC,
true) +
"]" + std::move(sub);
284 m_provider->GetPrivKey(pos, arg,
out);
286 std::optional<CPubKey> GetRootPubKey()
const override
288 return m_provider->GetRootPubKey();
290 std::optional<CExtPubKey> GetRootExtPubKey()
const override
292 return m_provider->GetRootExtPubKey();
294 std::unique_ptr<PubkeyProvider> Clone()
const override
296 return std::make_unique<OriginPubkeyProvider>(m_expr_index, m_origin, m_provider->Clone(), m_apostrophe);
301class ConstPubkeyProvider final :
public PubkeyProvider
310 arg.
GetKey(m_pubkey.GetID(), key)))
return std::nullopt;
315 ConstPubkeyProvider(uint32_t exp_index,
const CPubKey& pubkey,
bool xonly) : PubkeyProvider(exp_index), m_pubkey(pubkey), m_xonly(xonly) {}
319 CKeyID keyid = m_pubkey.GetID();
321 out.origins.emplace(keyid, std::make_pair(m_pubkey, info));
322 out.pubkeys.emplace(keyid, m_pubkey);
325 bool IsRange()
const override {
return false; }
326 size_t GetSize()
const override {
return m_pubkey.size(); }
327 bool IsBIP32()
const override {
return false; }
328 std::string
ToString(StringType type)
const override {
return m_xonly ?
HexStr(m_pubkey).substr(2) :
HexStr(m_pubkey); }
331 std::optional<CKey> key = GetPrivKey(arg);
332 if (!key)
return false;
343 std::optional<CKey> key = GetPrivKey(arg);
345 out.keys.emplace(key->GetPubKey().GetID(), *key);
347 std::optional<CPubKey> GetRootPubKey()
const override
351 std::optional<CExtPubKey> GetRootExtPubKey()
const override
355 std::unique_ptr<PubkeyProvider> Clone()
const override
357 return std::make_unique<ConstPubkeyProvider>(m_expr_index, m_pubkey, m_xonly);
361enum class DeriveType {
368class BIP32PubkeyProvider final :
public PubkeyProvider
380 if (!arg.
GetKey(m_root_extkey.pubkey.GetID(), key))
return false;
381 ret.nDepth = m_root_extkey.nDepth;
382 std::copy(m_root_extkey.vchFingerprint, m_root_extkey.vchFingerprint +
sizeof(
ret.vchFingerprint),
ret.vchFingerprint);
383 ret.nChild = m_root_extkey.nChild;
384 ret.chaincode = m_root_extkey.chaincode;
392 if (!GetExtKey(arg, xprv))
return false;
393 for (
auto entry : m_path) {
394 if (!xprv.
Derive(xprv, entry))
return false;
396 last_hardened = xprv;
402 bool IsHardened()
const
404 if (m_derive == DeriveType::HARDENED)
return true;
405 for (
auto entry : m_path) {
406 if (entry >> 31)
return true;
412 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) {}
413 bool IsRange()
const override {
return m_derive != DeriveType::NO; }
414 size_t GetSize()
const override {
return 33; }
415 bool IsBIP32()
const override {
return true; }
419 CKeyID keyid = m_root_extkey.pubkey.GetID();
422 if (m_derive == DeriveType::UNHARDENED) info.
path.push_back((uint32_t)pos);
423 if (m_derive == DeriveType::HARDENED) info.
path.push_back(((uint32_t)pos) | 0x80000000L);
431 if (!read_cache->GetCachedDerivedExtPubKey(m_expr_index, pos, final_extkey)) {
432 if (m_derive == DeriveType::HARDENED)
return std::nullopt;
434 if (!read_cache->GetCachedParentExtPubKey(m_expr_index, parent_extkey))
return std::nullopt;
435 final_extkey = parent_extkey;
436 if (m_derive == DeriveType::UNHARDENED) der = parent_extkey.
Derive(final_extkey, pos);
438 }
else if (IsHardened()) {
441 if (!GetDerivedExtKey(arg, xprv, lh_xprv))
return std::nullopt;
442 parent_extkey = xprv.
Neuter();
443 if (m_derive == DeriveType::UNHARDENED) der = xprv.
Derive(xprv, pos);
444 if (m_derive == DeriveType::HARDENED) der = xprv.
Derive(xprv, pos | 0x80000000UL);
445 final_extkey = xprv.
Neuter();
447 last_hardened_extkey = lh_xprv.
Neuter();
450 for (
auto entry : m_path) {
451 if (!parent_extkey.
Derive(parent_extkey, entry))
return std::nullopt;
453 final_extkey = parent_extkey;
454 if (m_derive == DeriveType::UNHARDENED) der = parent_extkey.
Derive(final_extkey, pos);
455 assert(m_derive != DeriveType::HARDENED);
457 if (!der)
return std::nullopt;
464 if (m_derive != DeriveType::HARDENED) {
465 write_cache->CacheParentExtPubKey(m_expr_index, parent_extkey);
468 write_cache->CacheLastHardenedExtPubKey(m_expr_index, last_hardened_extkey);
470 }
else if (info.
path.size() > 0) {
471 write_cache->CacheDerivedExtPubKey(m_expr_index, pos, final_extkey);
475 return final_extkey.
pubkey;
477 std::string
ToString(StringType type,
bool normalized)
const
480 const bool use_apostrophe = (!normalized && m_apostrophe) || type == StringType::COMPAT;
484 if (m_derive == DeriveType::HARDENED)
ret += use_apostrophe ?
'\'' :
'h';
488 std::string
ToString(StringType type=StringType::PUBLIC)
const override
495 if (!GetExtKey(arg, key))
return false;
499 if (m_derive == DeriveType::HARDENED)
out += m_apostrophe ?
'\'' :
'h';
505 if (m_derive == DeriveType::HARDENED) {
511 int i = (int)m_path.size() - 1;
512 for (; i >= 0; --i) {
513 if (m_path.at(i) >> 31) {
525 for (;
k <= i; ++
k) {
527 origin.
path.push_back(m_path.at(
k));
531 for (;
k < (int)m_path.size(); ++
k) {
532 end_path.push_back(m_path.at(
k));
535 CKeyID id = m_root_extkey.pubkey.GetID();
536 std::copy(
id.begin(),
id.begin() + 4, origin.
fingerprint);
541 if (cache !=
nullptr) {
547 if (!GetDerivedExtKey(arg, xprv, lh_xprv))
return false;
557 assert(m_derive == DeriveType::UNHARDENED);
565 if (!GetDerivedExtKey(arg, extkey, dummy))
return;
566 if (m_derive == DeriveType::UNHARDENED && !extkey.
Derive(extkey, pos))
return;
567 if (m_derive == DeriveType::HARDENED && !extkey.
Derive(extkey, pos | 0x80000000UL))
return;
570 std::optional<CPubKey> GetRootPubKey()
const override
574 std::optional<CExtPubKey> GetRootExtPubKey()
const override
576 return m_root_extkey;
578 std::unique_ptr<PubkeyProvider> Clone()
const override
580 return std::make_unique<BIP32PubkeyProvider>(m_expr_index, m_root_extkey, m_path, m_derive, m_apostrophe);
585class MuSigPubkeyProvider final :
public PubkeyProvider
589 const std::vector<std::unique_ptr<PubkeyProvider>> m_participants;
591 const KeyPath m_path;
593 mutable std::unique_ptr<PubkeyProvider> m_aggregate_provider;
594 mutable std::optional<CPubKey> m_aggregate_pubkey;
595 const DeriveType m_derive;
596 const bool m_ranged_participants;
598 bool IsRangedDerivation()
const {
return m_derive != DeriveType::NO; }
603 std::vector<std::unique_ptr<PubkeyProvider>> providers,
607 : PubkeyProvider(exp_index),
608 m_participants(
std::move(providers)),
609 m_path(
std::move(path)),
611 m_ranged_participants(
std::any_of(m_participants.begin(), m_participants.end(), [](const auto& pubkey) {
return pubkey->IsRange(); }))
613 if (!
Assume(!(m_ranged_participants && IsRangedDerivation()))) {
614 throw std::runtime_error(
"musig(): Cannot have both ranged participants and ranged derivation");
616 if (!
Assume(m_derive != DeriveType::HARDENED)) {
617 throw std::runtime_error(
"musig(): Cannot have hardened derivation");
625 if (!m_aggregate_provider && !m_ranged_participants) {
627 std::vector<CPubKey> pubkeys;
628 for (
const auto& prov : m_participants) {
629 std::optional<CPubKey> pubkey = prov->GetPubKey(0, arg, dummy, read_cache, write_cache);
630 if (!pubkey.has_value()) {
633 pubkeys.push_back(pubkey.value());
635 std::sort(pubkeys.begin(), pubkeys.end());
639 if (!
Assume(m_aggregate_pubkey.has_value()))
return std::nullopt;
642 if (IsRangedDerivation() || !m_path.empty()) {
645 m_aggregate_provider = std::make_unique<BIP32PubkeyProvider>(m_expr_index, extpub, m_path, m_derive,
false);
647 m_aggregate_provider = std::make_unique<ConstPubkeyProvider>(m_expr_index, m_aggregate_pubkey.value(),
false);
652 std::vector<CPubKey> pubkeys;
653 for (
const auto& prov : m_participants) {
654 std::optional<CPubKey> pub = prov->GetPubKey(pos, arg,
out, read_cache, write_cache);
655 if (!pub)
return std::nullopt;
656 pubkeys.emplace_back(*pub);
658 std::sort(pubkeys.begin(), pubkeys.end());
661 if (m_aggregate_provider) {
665 std::optional<CPubKey> pub = m_aggregate_provider->GetPubKey(pos, dummy,
out, read_cache, write_cache);
666 if (!pub)
return std::nullopt;
668 out.aggregate_pubkeys.emplace(m_aggregate_pubkey.value(), pubkeys);
670 if (!
Assume(m_ranged_participants) || !
Assume(m_path.empty()))
return std::nullopt;
673 if (!aggregate_pubkey)
return std::nullopt;
674 pubout = *aggregate_pubkey;
676 std::unique_ptr<ConstPubkeyProvider> this_agg_provider = std::make_unique<ConstPubkeyProvider>(m_expr_index, aggregate_pubkey.value(),
false);
677 this_agg_provider->GetPubKey(0, dummy,
out, read_cache, write_cache);
678 out.aggregate_pubkeys.emplace(pubout, pubkeys);
684 bool IsRange()
const override {
return IsRangedDerivation() || m_ranged_participants; }
686 size_t GetSize()
const override {
return 32; }
688 std::string
ToString(StringType type=StringType::PUBLIC)
const override
690 std::string
out =
"musig(";
691 for (
size_t i = 0; i < m_participants.size(); ++i) {
692 const auto& pubkey = m_participants.at(i);
694 out += pubkey->ToString(type);
698 if (IsRangedDerivation()) {
705 bool any_privkeys =
false;
707 for (
size_t i = 0; i < m_participants.size(); ++i) {
708 const auto& pubkey = m_participants.at(i);
711 if (pubkey->ToPrivateString(arg, tmp)) {
715 out += pubkey->ToString();
720 if (IsRangedDerivation()) {
723 if (!any_privkeys)
out.clear();
729 for (
size_t i = 0; i < m_participants.size(); ++i) {
730 const auto& pubkey = m_participants.at(i);
733 if (!pubkey->ToNormalizedString(arg, tmp, cache)) {
740 if (IsRangedDerivation()) {
751 for (
const auto& prov : m_participants) {
752 prov->GetPrivKey(pos, arg,
out);
761 std::optional<CPubKey> GetRootPubKey()
const override
765 std::optional<CExtPubKey> GetRootExtPubKey()
const override
770 std::unique_ptr<PubkeyProvider> Clone()
const override
772 std::vector<std::unique_ptr<PubkeyProvider>> providers;
773 providers.reserve(m_participants.size());
774 for (
const std::unique_ptr<PubkeyProvider>& p : m_participants) {
775 providers.emplace_back(p->Clone());
777 return std::make_unique<MuSigPubkeyProvider>(m_expr_index, std::move(providers), m_path, m_derive);
779 bool IsBIP32()
const override
782 return std::all_of(m_participants.begin(), m_participants.end(), [](
const auto& pubkey) { return pubkey->IsBIP32(); });
791 const std::vector<std::unique_ptr<PubkeyProvider>> m_pubkey_args;
793 const std::string m_name;
795 std::vector<std::string> m_warnings;
801 const std::vector<std::unique_ptr<DescriptorImpl>> m_subdescriptor_args;
804 virtual std::string ToStringExtra()
const {
return ""; }
816 virtual std::vector<CScript> MakeScripts(
const std::vector<CPubKey>& pubkeys, std::span<const CScript> scripts,
FlatSigningProvider&
out)
const = 0;
819 DescriptorImpl(std::vector<std::unique_ptr<PubkeyProvider>> pubkeys,
const std::string&
name) : m_pubkey_args(
std::move(pubkeys)), m_name(
name), m_subdescriptor_args() {}
820 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))) {}
821 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)) {}
823 enum class StringType
834 for (
const auto& arg : m_subdescriptor_args) {
835 if (!arg->IsSolvable())
return false;
843 for (
const auto& pubkey : m_pubkey_args) {
844 if (pubkey->IsRange())
return true;
846 for (
const auto& arg : m_subdescriptor_args) {
847 if (arg->IsRange())
return true;
856 for (
const auto& scriptarg : m_subdescriptor_args) {
857 if (pos++)
ret +=
",";
859 if (!scriptarg->ToStringHelper(arg, tmp, type, cache))
return false;
868 std::string extra = ToStringExtra();
869 size_t pos = extra.size() > 0 ? 1 : 0;
870 std::string
ret = m_name +
"(" + extra;
871 for (
const auto& pubkey : m_pubkey_args) {
872 if (pos++)
ret +=
",";
875 case StringType::NORMALIZED:
876 if (!pubkey->ToNormalizedString(*arg, tmp, cache))
return false;
878 case StringType::PRIVATE:
879 if (!pubkey->ToPrivateString(*arg, tmp))
return false;
881 case StringType::PUBLIC:
882 tmp = pubkey->ToString();
884 case StringType::COMPAT:
885 tmp = pubkey->ToString(PubkeyProvider::StringType::COMPAT);
890 std::string subscript;
891 if (!ToStringSubScriptHelper(arg, subscript, type, cache))
return false;
892 if (pos && subscript.size())
ret +=
',';
893 out = std::move(
ret) + std::move(subscript) +
")";
897 std::string
ToString(
bool compat_format)
const final
900 ToStringHelper(
nullptr,
ret, compat_format ? StringType::COMPAT : StringType::PUBLIC);
901 return AddChecksum(
ret);
906 bool ret = ToStringHelper(&arg,
out, StringType::PRIVATE);
913 bool ret = ToStringHelper(&arg,
out, StringType::NORMALIZED, cache);
922 std::vector<CPubKey> pubkeys;
923 pubkeys.reserve(m_pubkey_args.size());
926 for (
const auto& p : m_pubkey_args) {
927 std::optional<CPubKey> pubkey = p->
GetPubKey(pos, arg, subprovider, read_cache, write_cache);
928 if (!pubkey)
return false;
929 pubkeys.push_back(pubkey.value());
931 std::vector<CScript> subscripts;
932 for (
const auto& subarg : m_subdescriptor_args) {
933 std::vector<CScript> outscripts;
934 if (!subarg->ExpandHelper(pos, arg, read_cache, outscripts, subprovider, write_cache))
return false;
935 assert(outscripts.size() == 1);
936 subscripts.emplace_back(std::move(outscripts[0]));
938 out.Merge(std::move(subprovider));
940 output_scripts = MakeScripts(pubkeys, std::span{subscripts},
out);
946 return ExpandHelper(pos, provider,
nullptr, output_scripts,
out, write_cache);
957 for (
const auto& p : m_pubkey_args) {
958 p->GetPrivKey(pos, provider,
out);
960 for (
const auto& arg : m_subdescriptor_args) {
961 arg->ExpandPrivate(pos, provider,
out);
965 std::optional<OutputType>
GetOutputType()
const override {
return std::nullopt; }
967 std::optional<int64_t>
ScriptSize()
const override {
return {}; }
974 virtual std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const {
return {}; }
981 void GetPubKeys(std::set<CPubKey>& pubkeys, std::set<CExtPubKey>& ext_pubs)
const override
983 for (
const auto& p : m_pubkey_args) {
984 std::optional<CPubKey> pub = p->GetRootPubKey();
985 if (pub) pubkeys.insert(*pub);
986 std::optional<CExtPubKey> ext_pub = p->GetRootExtPubKey();
987 if (ext_pub) ext_pubs.insert(*ext_pub);
989 for (
const auto& arg : m_subdescriptor_args) {
990 arg->GetPubKeys(pubkeys, ext_pubs);
994 virtual std::unique_ptr<DescriptorImpl> Clone()
const = 0;
997 std::vector<std::string>
Warnings()
const override {
998 std::vector<std::string> all = m_warnings;
999 for (
const auto& sub : m_subdescriptor_args) {
1000 auto sub_w = sub->Warnings();
1001 all.insert(all.end(), sub_w.begin(), sub_w.end());
1008class AddressDescriptor final :
public DescriptorImpl
1012 std::string ToStringExtra()
const override {
return EncodeDestination(m_destination); }
1015 AddressDescriptor(
CTxDestination destination) : DescriptorImpl({},
"addr"), m_destination(std::move(destination)) {}
1016 bool IsSolvable() const final {
return false; }
1022 bool IsSingleType() const final {
return true; }
1023 bool ToPrivateString(
const SigningProvider& arg, std::string&
out)
const final {
return false; }
1026 std::unique_ptr<DescriptorImpl> Clone()
const override
1028 return std::make_unique<AddressDescriptor>(m_destination);
1033class RawDescriptor final :
public DescriptorImpl
1037 std::string ToStringExtra()
const override {
return HexStr(m_script); }
1038 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>&, std::span<const CScript>,
FlatSigningProvider&)
const override {
return Vector(m_script); }
1041 bool IsSolvable() const final {
return false; }
1049 bool IsSingleType() const final {
return true; }
1050 bool ToPrivateString(
const SigningProvider& arg, std::string&
out)
const final {
return false; }
1052 std::optional<int64_t> ScriptSize()
const override {
return m_script.size(); }
1054 std::unique_ptr<DescriptorImpl> Clone()
const override
1056 return std::make_unique<RawDescriptor>(m_script);
1061class PKDescriptor final :
public DescriptorImpl
1066 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>& keys, std::span<const CScript>,
FlatSigningProvider&)
const override
1076 PKDescriptor(std::unique_ptr<PubkeyProvider> prov,
bool xonly =
false) : DescriptorImpl(
Vector(
std::move(prov)),
"pk"), m_xonly(xonly) {}
1077 bool IsSingleType() const final {
return true; }
1079 std::optional<int64_t> ScriptSize()
const override {
1080 return 1 + (m_xonly ? 32 : m_pubkey_args[0]->GetSize()) + 1;
1083 std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const override {
1084 const auto ecdsa_sig_size = use_max_sig ? 72 : 71;
1085 return 1 + (m_xonly ? 65 : ecdsa_sig_size);
1088 std::optional<int64_t> MaxSatisfactionWeight(
bool use_max_sig)
const override {
1092 std::optional<int64_t> MaxSatisfactionElems()
const override {
return 1; }
1094 std::unique_ptr<DescriptorImpl> Clone()
const override
1096 return std::make_unique<PKDescriptor>(m_pubkey_args.at(0)->Clone(), m_xonly);
1101class PKHDescriptor final :
public DescriptorImpl
1104 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>& keys, std::span<const CScript>,
FlatSigningProvider&)
const override
1106 CKeyID id = keys[0].GetID();
1110 PKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(
Vector(
std::move(prov)),
"pkh") {}
1112 bool IsSingleType() const final {
return true; }
1114 std::optional<int64_t> ScriptSize()
const override {
return 1 + 1 + 1 + 20 + 1 + 1; }
1116 std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const override {
1117 const auto sig_size = use_max_sig ? 72 : 71;
1118 return 1 +
sig_size + 1 + m_pubkey_args[0]->GetSize();
1121 std::optional<int64_t> MaxSatisfactionWeight(
bool use_max_sig)
const override {
1125 std::optional<int64_t> MaxSatisfactionElems()
const override {
return 2; }
1127 std::unique_ptr<DescriptorImpl> Clone()
const override
1129 return std::make_unique<PKHDescriptor>(m_pubkey_args.at(0)->Clone());
1134class WPKHDescriptor final :
public DescriptorImpl
1137 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>& keys, std::span<const CScript>,
FlatSigningProvider&)
const override
1139 CKeyID id = keys[0].GetID();
1143 WPKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(
Vector(
std::move(prov)),
"wpkh") {}
1145 bool IsSingleType() const final {
return true; }
1147 std::optional<int64_t> ScriptSize()
const override {
return 1 + 1 + 20; }
1149 std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const override {
1150 const auto sig_size = use_max_sig ? 72 : 71;
1154 std::optional<int64_t> MaxSatisfactionWeight(
bool use_max_sig)
const override {
1155 return MaxSatSize(use_max_sig);
1158 std::optional<int64_t> MaxSatisfactionElems()
const override {
return 2; }
1160 std::unique_ptr<DescriptorImpl> Clone()
const override
1162 return std::make_unique<WPKHDescriptor>(m_pubkey_args.at(0)->Clone());
1167class ComboDescriptor final :
public DescriptorImpl
1170 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>& keys, std::span<const CScript>,
FlatSigningProvider&
out)
const override
1172 std::vector<CScript>
ret;
1173 CKeyID id = keys[0].GetID();
1176 if (keys[0].IsCompressed()) {
1179 ret.emplace_back(p2wpkh);
1185 ComboDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(
Vector(
std::move(prov)),
"combo") {}
1186 bool IsSingleType() const final {
return false; }
1187 std::unique_ptr<DescriptorImpl> Clone()
const override
1189 return std::make_unique<ComboDescriptor>(m_pubkey_args.at(0)->Clone());
1194class MultisigDescriptor final :
public DescriptorImpl
1196 const int m_threshold;
1197 const bool m_sorted;
1199 std::string ToStringExtra()
const override {
return strprintf(
"%i", m_threshold); }
1200 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>& keys, std::span<const CScript>,
FlatSigningProvider&)
const override {
1202 std::vector<CPubKey> sorted_keys(keys);
1203 std::sort(sorted_keys.begin(), sorted_keys.end());
1209 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) {}
1210 bool IsSingleType() const final {
return true; }
1212 std::optional<int64_t> ScriptSize()
const override {
1213 const auto n_keys = m_pubkey_args.size();
1214 auto op = [](int64_t acc,
const std::unique_ptr<PubkeyProvider>&
pk) {
return acc + 1 +
pk->GetSize();};
1215 const auto pubkeys_size{std::accumulate(m_pubkey_args.begin(), m_pubkey_args.end(), int64_t{0}, op)};
1219 std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const override {
1220 const auto sig_size = use_max_sig ? 72 : 71;
1221 return (1 + (1 +
sig_size) * m_threshold);
1224 std::optional<int64_t> MaxSatisfactionWeight(
bool use_max_sig)
const override {
1228 std::optional<int64_t> MaxSatisfactionElems()
const override {
return 1 + m_threshold; }
1230 std::unique_ptr<DescriptorImpl> Clone()
const override
1232 std::vector<std::unique_ptr<PubkeyProvider>> providers;
1233 providers.reserve(m_pubkey_args.size());
1234 std::transform(m_pubkey_args.begin(), m_pubkey_args.end(), providers.begin(), [](
const std::unique_ptr<PubkeyProvider>& p) { return p->Clone(); });
1235 return std::make_unique<MultisigDescriptor>(m_threshold, std::move(providers), m_sorted);
1240class MultiADescriptor final :
public DescriptorImpl
1242 const int m_threshold;
1243 const bool m_sorted;
1245 std::string ToStringExtra()
const override {
return strprintf(
"%i", m_threshold); }
1246 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>& keys, std::span<const CScript>,
FlatSigningProvider&)
const override {
1248 std::vector<XOnlyPubKey> xkeys;
1249 xkeys.reserve(keys.size());
1250 for (
const auto& key : keys) xkeys.emplace_back(key);
1251 if (m_sorted) std::sort(xkeys.begin(), xkeys.end());
1253 for (
size_t i = 1; i < keys.size(); ++i) {
1260 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) {}
1261 bool IsSingleType() const final {
return true; }
1263 std::optional<int64_t> ScriptSize()
const override {
1264 const auto n_keys = m_pubkey_args.size();
1268 std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const override {
1269 return (1 + 65) * m_threshold + (m_pubkey_args.size() - m_threshold);
1272 std::optional<int64_t> MaxSatisfactionElems()
const override {
return m_pubkey_args.size(); }
1274 std::unique_ptr<DescriptorImpl> Clone()
const override
1276 std::vector<std::unique_ptr<PubkeyProvider>> providers;
1277 providers.reserve(m_pubkey_args.size());
1278 for (
const auto& arg : m_pubkey_args) {
1279 providers.push_back(arg->Clone());
1281 return std::make_unique<MultiADescriptor>(m_threshold, std::move(providers), m_sorted);
1286class SHDescriptor final :
public DescriptorImpl
1289 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>&, std::span<const CScript> scripts,
FlatSigningProvider&
out)
const override
1292 if (
ret.size())
out.scripts.emplace(
CScriptID(scripts[0]), scripts[0]);
1299 SHDescriptor(std::unique_ptr<DescriptorImpl> desc) : DescriptorImpl({}, std::move(desc),
"sh") {}
1303 assert(m_subdescriptor_args.size() == 1);
1307 bool IsSingleType() const final {
return true; }
1309 std::optional<int64_t> ScriptSize()
const override {
return 1 + 1 + 20 + 1; }
1311 std::optional<int64_t> MaxSatisfactionWeight(
bool use_max_sig)
const override {
1312 if (
const auto sat_size = m_subdescriptor_args[0]->MaxSatSize(use_max_sig)) {
1313 if (
const auto subscript_size = m_subdescriptor_args[0]->ScriptSize()) {
1317 if (
IsSegwit())
return subscript_weight + *sat_size;
1324 std::optional<int64_t> MaxSatisfactionElems()
const override {
1325 if (
const auto sub_elems = m_subdescriptor_args[0]->MaxSatisfactionElems())
return 1 + *sub_elems;
1329 std::unique_ptr<DescriptorImpl> Clone()
const override
1331 return std::make_unique<SHDescriptor>(m_subdescriptor_args.at(0)->Clone());
1336class WSHDescriptor final :
public DescriptorImpl
1339 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>&, std::span<const CScript> scripts,
FlatSigningProvider&
out)
const override
1342 if (
ret.size())
out.scripts.emplace(
CScriptID(scripts[0]), scripts[0]);
1346 WSHDescriptor(std::unique_ptr<DescriptorImpl> desc) : DescriptorImpl({}, std::move(desc),
"wsh") {}
1348 bool IsSingleType() const final {
return true; }
1350 std::optional<int64_t> ScriptSize()
const override {
return 1 + 1 + 32; }
1352 std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const override {
1353 if (
const auto sat_size = m_subdescriptor_args[0]->MaxSatSize(use_max_sig)) {
1354 if (
const auto subscript_size = m_subdescriptor_args[0]->ScriptSize()) {
1361 std::optional<int64_t> MaxSatisfactionWeight(
bool use_max_sig)
const override {
1362 return MaxSatSize(use_max_sig);
1365 std::optional<int64_t> MaxSatisfactionElems()
const override {
1366 if (
const auto sub_elems = m_subdescriptor_args[0]->MaxSatisfactionElems())
return 1 + *sub_elems;
1370 std::unique_ptr<DescriptorImpl> Clone()
const override
1372 return std::make_unique<WSHDescriptor>(m_subdescriptor_args.at(0)->Clone());
1377class TRDescriptor final :
public DescriptorImpl
1379 std::vector<int> m_depths;
1381 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>& keys, std::span<const CScript> scripts,
FlatSigningProvider&
out)
const override
1384 assert(m_depths.size() == scripts.size());
1385 for (
size_t pos = 0; pos < m_depths.size(); ++pos) {
1389 assert(keys.size() == 1);
1391 if (!xpk.IsFullyValid())
return {};
1394 out.tr_trees[output] = builder;
1399 if (m_depths.empty())
return true;
1400 std::vector<bool> path;
1401 for (
size_t pos = 0; pos < m_depths.size(); ++pos) {
1402 if (pos)
ret +=
',';
1403 while ((
int)path.size() <= m_depths[pos]) {
1404 if (path.size())
ret +=
'{';
1405 path.push_back(
false);
1408 if (!m_subdescriptor_args[pos]->ToStringHelper(arg, tmp, type, cache))
return false;
1410 while (!path.empty() && path.back()) {
1411 if (path.size() > 1)
ret +=
'}';
1414 if (!path.empty()) path.back() =
true;
1419 TRDescriptor(std::unique_ptr<PubkeyProvider> internal_key, std::vector<std::unique_ptr<DescriptorImpl>> descs, std::vector<int> depths) :
1420 DescriptorImpl(
Vector(
std::move(internal_key)),
std::move(descs),
"tr"), m_depths(
std::move(depths))
1422 assert(m_subdescriptor_args.size() == m_depths.size());
1425 bool IsSingleType() const final {
return true; }
1427 std::optional<int64_t> ScriptSize()
const override {
return 1 + 1 + 32; }
1429 std::optional<int64_t> MaxSatisfactionWeight(
bool)
const override {
1434 std::optional<int64_t> MaxSatisfactionElems()
const override {
1439 std::unique_ptr<DescriptorImpl> Clone()
const override
1441 std::vector<std::unique_ptr<DescriptorImpl>> subdescs;
1442 subdescs.reserve(m_subdescriptor_args.size());
1443 std::transform(m_subdescriptor_args.begin(), m_subdescriptor_args.end(), subdescs.begin(), [](
const std::unique_ptr<DescriptorImpl>& d) { return d->Clone(); });
1444 return std::make_unique<TRDescriptor>(m_pubkey_args.at(0)->Clone(), std::move(subdescs), m_depths);
1458 const std::vector<CPubKey>& m_keys;
1465 uint160 GetHash160(uint32_t key)
const {
1469 return m_keys[key].GetID();
1475 std::vector<unsigned char> ToPKBytes(uint32_t key)
const {
1478 return {m_keys[key].begin(), m_keys[key].end()};
1481 return {xonly_pubkey.
begin(), xonly_pubkey.end()};
1484 std::vector<unsigned char> ToPKHBytes(uint32_t key)
const {
1485 auto id = GetHash160(key);
1486 return {
id.begin(),
id.end()};
1497 const std::vector<std::unique_ptr<PubkeyProvider>>& m_pubkeys;
1499 const DescriptorImpl::StringType m_type;
1504 const std::vector<std::unique_ptr<PubkeyProvider>>& pubkeys
LIFETIMEBOUND,
1505 DescriptorImpl::StringType type,
1507 : m_arg(arg), m_pubkeys(pubkeys), m_type(type), m_cache(cache) {}
1509 std::optional<std::string>
ToString(uint32_t key)
const
1513 case DescriptorImpl::StringType::PUBLIC:
1514 ret = m_pubkeys[key]->ToString();
1516 case DescriptorImpl::StringType::PRIVATE:
1517 if (!m_pubkeys[key]->ToPrivateString(*m_arg,
ret))
return {};
1519 case DescriptorImpl::StringType::NORMALIZED:
1520 if (!m_pubkeys[key]->ToNormalizedString(*m_arg,
ret, m_cache))
return {};
1522 case DescriptorImpl::StringType::COMPAT:
1523 ret = m_pubkeys[key]->ToString(PubkeyProvider::StringType::COMPAT);
1530class MiniscriptDescriptor final :
public DescriptorImpl
1536 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>& keys, std::span<const CScript> scripts,
1539 const auto script_ctx{
m_node->GetMsCtx()};
1540 for (
const auto& key : keys) {
1544 provider.
pubkeys.emplace(key.GetID(), key);
1547 return Vector(
m_node->ToScript(ScriptMaker(keys, script_ctx)));
1557 const uint32_t raw = node.k;
1558 const uint32_t value_part = raw & ~CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG;
1559 if (value_part > CTxIn::SEQUENCE_LOCKTIME_MASK) {
1560 const bool is_time_based = (raw & CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG) != 0;
1561 if (is_time_based) {
1562 m_warnings.push_back(strprintf(
"time-based relative locktime: older(%u) > (65535 * 512) seconds is unsafe", raw));
1564 m_warnings.push_back(strprintf(
"height-based relative locktime: older(%u) > 65535 blocks is unsafe", raw));
1571 bool ToStringHelper(
const SigningProvider* arg, std::string&
out,
const StringType type,
1574 if (
const auto res =
m_node->ToString(StringMaker(arg, m_pubkey_args, type, cache))) {
1581 bool IsSolvable()
const override {
return true; }
1582 bool IsSingleType() const final {
return true; }
1584 std::optional<int64_t> ScriptSize()
const override {
return m_node->ScriptSize(); }
1586 std::optional<int64_t> MaxSatSize(
bool)
const override {
1588 return m_node->GetWitnessSize();
1591 std::optional<int64_t> MaxSatisfactionElems()
const override {
1592 return m_node->GetStackSize();
1595 std::unique_ptr<DescriptorImpl> Clone()
const override
1597 std::vector<std::unique_ptr<PubkeyProvider>> providers;
1598 providers.reserve(m_pubkey_args.size());
1599 for (
const auto& arg : m_pubkey_args) {
1600 providers.push_back(arg->Clone());
1602 return std::make_unique<MiniscriptDescriptor>(std::move(providers),
m_node->Clone());
1607class RawTRDescriptor final :
public DescriptorImpl
1610 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>& keys, std::span<const CScript> scripts,
FlatSigningProvider&
out)
const override
1612 assert(keys.size() == 1);
1614 if (!xpk.IsFullyValid())
return {};
1619 RawTRDescriptor(std::unique_ptr<PubkeyProvider> output_key) : DescriptorImpl(
Vector(
std::move(output_key)),
"rawtr") {}
1621 bool IsSingleType() const final {
return true; }
1623 std::optional<int64_t> ScriptSize()
const override {
return 1 + 1 + 32; }
1625 std::optional<int64_t> MaxSatisfactionWeight(
bool)
const override {
1630 std::optional<int64_t> MaxSatisfactionElems()
const override {
1635 std::unique_ptr<DescriptorImpl> Clone()
const override
1637 return std::make_unique<RawTRDescriptor>(m_pubkey_args.at(0)->Clone());
1645enum class ParseScriptContext {
1654std::optional<uint32_t> ParseKeyPathNum(std::span<const char> elem,
bool& apostrophe, std::string& error,
bool& has_hardened)
1656 bool hardened =
false;
1657 if (elem.size() > 0) {
1658 const char last = elem[elem.size() - 1];
1659 if (last ==
'\'' || last ==
'h') {
1660 elem = elem.first(elem.size() - 1);
1662 apostrophe = last ==
'\'';
1665 const auto p{ToIntegral<uint32_t>(std::string_view{elem.begin(), elem.end()})};
1667 error =
strprintf(
"Key path value '%s' is not a valid uint32", std::string_view{elem.begin(), elem.end()});
1668 return std::nullopt;
1669 }
else if (*p > 0x7FFFFFFFUL) {
1670 error =
strprintf(
"Key path value %u is out of range", *p);
1671 return std::nullopt;
1673 has_hardened = has_hardened || hardened;
1675 return std::make_optional<uint32_t>(*p | (((uint32_t)hardened) << 31));
1689[[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)
1692 struct MultipathSubstitutes {
1693 size_t placeholder_index;
1694 std::vector<uint32_t>
values;
1696 std::optional<MultipathSubstitutes> substitutes;
1697 has_hardened =
false;
1699 for (
size_t i = 1; i <
split.size(); ++i) {
1700 const std::span<const char>& elem =
split[i];
1703 if (!elem.empty() && elem.front() ==
'<' && elem.back() ==
'>') {
1704 if (!allow_multipath) {
1705 error =
strprintf(
"Key path value '%s' specifies multipath in a section where multipath is not allowed", std::string(elem.begin(), elem.end()));
1709 error =
"Multiple multipath key path specifiers found";
1714 std::vector<std::span<const char>> nums =
Split(std::span(elem.begin()+1, elem.end()-1),
";");
1715 if (nums.size() < 2) {
1716 error =
"Multipath key path specifiers must have at least two items";
1720 substitutes.emplace();
1721 std::unordered_set<uint32_t> seen_substitutes;
1722 for (
const auto& num : nums) {
1723 const auto& op_num = ParseKeyPathNum(num, apostrophe, error, has_hardened);
1724 if (!op_num)
return false;
1725 auto [
_, inserted] = seen_substitutes.insert(*op_num);
1727 error =
strprintf(
"Duplicated key path value %u in multipath specifier", *op_num);
1730 substitutes->values.emplace_back(*op_num);
1733 path.emplace_back();
1734 substitutes->placeholder_index = path.size() - 1;
1736 const auto& op_num = ParseKeyPathNum(elem, apostrophe, error, has_hardened);
1737 if (!op_num)
return false;
1738 path.emplace_back(*op_num);
1743 out.emplace_back(std::move(path));
1746 for (uint32_t substitute : substitutes->values) {
1747 KeyPath branch_path = path;
1748 branch_path[substitutes->placeholder_index] = substitute;
1749 out.emplace_back(std::move(branch_path));
1755[[nodiscard]]
bool ParseKeyPath(
const std::vector<std::span<const char>>&
split, std::vector<KeyPath>&
out,
bool& apostrophe, std::string& error,
bool allow_multipath)
1758 return ParseKeyPath(
split,
out, apostrophe, error, allow_multipath, dummy);
1761static DeriveType ParseDeriveType(std::vector<std::span<const char>>&
split,
bool& apostrophe)
1763 DeriveType type = DeriveType::NO;
1764 if (std::ranges::equal(
split.back(), std::span{
"*"}.first(1))) {
1766 type = DeriveType::UNHARDENED;
1767 }
else if (std::ranges::equal(
split.back(), std::span{
"*'"}.first(2)) || std::ranges::equal(
split.back(), std::span{
"*h"}.first(2))) {
1768 apostrophe = std::ranges::equal(
split.back(), std::span{
"*'"}.first(2));
1770 type = DeriveType::HARDENED;
1776std::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)
1778 std::vector<std::unique_ptr<PubkeyProvider>>
ret;
1779 bool permit_uncompressed = ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH;
1781 std::string str(
split[0].begin(),
split[0].end());
1782 if (str.size() == 0) {
1783 error =
"No key provided";
1787 error =
strprintf(
"Key '%s' is invalid due to whitespace", str);
1790 if (
split.size() == 1) {
1794 if (pubkey.IsValid() && !pubkey.IsValidNonHybrid()) {
1795 error =
"Hybrid public keys are not allowed";
1798 if (pubkey.IsFullyValid()) {
1799 if (permit_uncompressed || pubkey.IsCompressed()) {
1800 ret.emplace_back(std::make_unique<ConstPubkeyProvider>(key_exp_index, pubkey,
false));
1803 error =
"Uncompressed keys are not allowed";
1806 }
else if (
data.size() == 32 && ctx == ParseScriptContext::P2TR) {
1807 unsigned char fullkey[33] = {0x02};
1808 std::copy(
data.begin(),
data.end(), fullkey + 1);
1809 pubkey.Set(std::begin(fullkey), std::end(fullkey));
1810 if (pubkey.IsFullyValid()) {
1811 ret.emplace_back(std::make_unique<ConstPubkeyProvider>(key_exp_index, pubkey,
true));
1815 error =
strprintf(
"Pubkey '%s' is invalid", str);
1822 out.keys.emplace(pubkey.
GetID(), key);
1823 ret.emplace_back(std::make_unique<ConstPubkeyProvider>(key_exp_index, pubkey, ctx == ParseScriptContext::P2TR));
1826 error =
"Uncompressed keys are not allowed";
1834 error =
strprintf(
"key '%s' is not valid", str);
1837 std::vector<KeyPath> paths;
1838 DeriveType type = ParseDeriveType(
split, apostrophe);
1839 if (!ParseKeyPath(
split, paths, apostrophe, error,
true))
return {};
1841 extpubkey = extkey.
Neuter();
1844 for (
auto& path : paths) {
1845 ret.emplace_back(std::make_unique<BIP32PubkeyProvider>(key_exp_index, extpubkey, std::move(path), type, apostrophe));
1852std::vector<std::unique_ptr<PubkeyProvider>> ParsePubkey(uint32_t& key_exp_index,
const std::span<const char>& sp, ParseScriptContext ctx,
FlatSigningProvider&
out, std::string& error)
1854 std::vector<std::unique_ptr<PubkeyProvider>>
ret;
1859 std::span<const char> span = sp;
1860 if (
Const(
"musig(", span,
false)) {
1861 if (ctx != ParseScriptContext::P2TR) {
1862 error =
"musig() is only allowed in tr() and rawtr()";
1869 if (
split.size() > 2) {
1870 error =
"Too many ')' in musig() expression";
1873 std::span<const char> expr(
split.at(0).begin(),
split.at(0).end());
1874 if (!
Func(
"musig", expr)) {
1875 error =
"Invalid musig() expression";
1880 bool any_ranged =
false;
1881 bool all_bip32 =
true;
1882 std::vector<std::vector<std::unique_ptr<PubkeyProvider>>> providers;
1883 bool any_key_parsed =
false;
1884 size_t max_multipath_len = 0;
1885 while (expr.size()) {
1886 if (any_key_parsed && !
Const(
",", expr)) {
1887 error =
strprintf(
"musig(): expected ',', got '%c'", expr[0]);
1890 auto arg =
Expr(expr);
1891 auto pk = ParsePubkey(key_exp_index, arg, ParseScriptContext::MUSIG,
out, error);
1893 error =
strprintf(
"musig(): %s", error);
1896 any_key_parsed =
true;
1898 any_ranged = any_ranged ||
pk.at(0)->IsRange();
1899 all_bip32 = all_bip32 &&
pk.at(0)->IsBIP32();
1901 max_multipath_len = std::max(max_multipath_len,
pk.size());
1903 providers.emplace_back(std::move(
pk));
1906 if (!any_key_parsed) {
1907 error =
"musig(): Must contain key expressions";
1912 DeriveType deriv_type = DeriveType::NO;
1913 std::vector<KeyPath> derivation_multipaths;
1916 error =
"musig(): derivation requires all participants to be xpubs or xprvs";
1920 error =
"musig(): Cannot have ranged participant keys if musig() also has derivation";
1925 deriv_type = ParseDeriveType(deriv_split, dummy);
1926 if (deriv_type == DeriveType::HARDENED) {
1927 error =
"musig(): Cannot have hardened child derivation";
1930 bool has_hardened =
false;
1931 if (!ParseKeyPath(deriv_split, derivation_multipaths, dummy, error,
true, has_hardened)) {
1932 error =
"musig(): " + error;
1936 error =
"musig(): cannot have hardened derivation steps";
1940 derivation_multipaths.emplace_back();
1945 const auto& clone_providers = [&providers](
size_t length) ->
bool {
1946 for (
auto& multipath_providers : providers) {
1947 if (multipath_providers.size() == 1) {
1948 for (
size_t i = 1; i < length; ++i) {
1949 multipath_providers.emplace_back(multipath_providers.at(0)->Clone());
1951 }
else if (multipath_providers.size() != length) {
1960 const auto& emplace_final_provider = [&
ret, &key_exp_index, &deriv_type, &derivation_multipaths, &providers](
size_t vec_idx,
size_t path_idx) ->
void {
1961 KeyPath& path = derivation_multipaths.at(path_idx);
1962 std::vector<std::unique_ptr<PubkeyProvider>> pubs;
1963 pubs.reserve(providers.size());
1964 for (
auto& vec : providers) {
1965 pubs.emplace_back(std::move(vec.at(vec_idx)));
1967 ret.emplace_back(std::make_unique<MuSigPubkeyProvider>(key_exp_index, std::move(pubs), path, deriv_type));
1970 if (max_multipath_len > 1 && derivation_multipaths.size() > 1) {
1971 error =
"musig(): Cannot have multipath participant keys if musig() is also multipath";
1973 }
else if (max_multipath_len > 1) {
1974 if (!clone_providers(max_multipath_len)) {
1975 error =
strprintf(
"musig(): Multipath derivation paths have mismatched lengths");
1978 for (
size_t i = 0; i < max_multipath_len; ++i) {
1980 emplace_final_provider(i, 0);
1982 }
else if (derivation_multipaths.size() > 1) {
1984 if (!
Assume(clone_providers(derivation_multipaths.size()))) {
1985 error =
"musig(): Multipath derivation path with multipath participants is disallowed";
1988 for (
size_t i = 0; i < derivation_multipaths.size(); ++i) {
1990 emplace_final_provider(i, i);
1994 emplace_final_provider(0, 0);
1999 auto origin_split =
Split(sp,
']');
2000 if (origin_split.size() > 2) {
2001 error =
"Multiple ']' characters found for a single pubkey";
2005 bool apostrophe =
false;
2006 if (origin_split.size() == 1) {
2007 return ParsePubkeyInner(key_exp_index, origin_split[0], ctx,
out, apostrophe, error);
2009 if (origin_split[0].empty() || origin_split[0][0] !=
'[') {
2010 error =
strprintf(
"Key origin start '[ character expected but not found, got '%c' instead",
2011 origin_split[0].empty() ?
']' : origin_split[0][0]);
2014 auto slash_split =
Split(origin_split[0].subspan(1),
'/');
2015 if (slash_split[0].size() != 8) {
2016 error =
strprintf(
"Fingerprint is not 4 bytes (%u characters instead of 8 characters)", slash_split[0].size());
2019 std::string fpr_hex = std::string(slash_split[0].begin(), slash_split[0].end());
2020 if (!
IsHex(fpr_hex)) {
2021 error =
strprintf(
"Fingerprint '%s' is not hex", fpr_hex);
2024 auto fpr_bytes =
ParseHex(fpr_hex);
2026 static_assert(
sizeof(info.
fingerprint) == 4,
"Fingerprint must be 4 bytes");
2027 assert(fpr_bytes.size() == 4);
2028 std::copy(fpr_bytes.begin(), fpr_bytes.end(), info.
fingerprint);
2029 std::vector<KeyPath> path;
2030 if (!ParseKeyPath(slash_split, path, apostrophe, error,
false))
return {};
2031 info.
path = path.at(0);
2032 auto providers = ParsePubkeyInner(key_exp_index, origin_split[1], ctx,
out, apostrophe, error);
2033 if (providers.empty())
return {};
2034 ret.reserve(providers.size());
2035 for (
auto& prov : providers) {
2036 ret.emplace_back(std::make_unique<OriginPubkeyProvider>(key_exp_index, info, std::move(prov), apostrophe));
2041std::unique_ptr<PubkeyProvider> InferPubkey(
const CPubKey& pubkey, ParseScriptContext ctx,
const SigningProvider& provider)
2048 if (ctx != ParseScriptContext::TOP && ctx != ParseScriptContext::P2SH && !pubkey.
IsCompressed()) {
2051 std::unique_ptr<PubkeyProvider> key_provider = std::make_unique<ConstPubkeyProvider>(0, pubkey,
false);
2054 return std::make_unique<OriginPubkeyProvider>(0, std::move(info), std::move(key_provider),
false);
2056 return key_provider;
2059std::unique_ptr<PubkeyProvider> InferXOnlyPubkey(
const XOnlyPubKey& xkey, ParseScriptContext ctx,
const SigningProvider& provider)
2062 std::unique_ptr<PubkeyProvider> key_provider = std::make_unique<ConstPubkeyProvider>(0, pubkey,
true);
2065 return std::make_unique<OriginPubkeyProvider>(0, std::move(info), std::move(key_provider),
false);
2067 return key_provider;
2075 using Key = uint32_t;
2081 mutable std::vector<std::vector<std::unique_ptr<PubkeyProvider>>> m_keys;
2083 mutable std::string m_key_parsing_error;
2091 : m_out(
out), m_in(in), m_script_ctx(ctx), m_offset(offset) {}
2093 bool KeyCompare(
const Key& a,
const Key& b)
const {
2094 return *m_keys.at(a).at(0) < *m_keys.at(b).at(0);
2098 switch (m_script_ctx) {
2105 template<
typename I> std::optional<Key>
FromString(I begin, I end)
const
2108 Key key = m_keys.
size();
2109 uint32_t exp_index = m_offset + key;
2110 auto pk = ParsePubkey(exp_index, {&*begin, &*end},
ParseContext(), *m_out, m_key_parsing_error);
2111 if (
pk.empty())
return {};
2112 m_keys.emplace_back(std::move(
pk));
2116 std::optional<std::string>
ToString(
const Key& key)
const
2118 return m_keys.at(key).at(0)->ToString();
2121 template<
typename I> std::optional<Key> FromPKBytes(I begin, I end)
const
2124 Key key = m_keys.size();
2127 std::copy(begin, end, pubkey.
begin());
2128 if (
auto pubkey_provider = InferXOnlyPubkey(pubkey,
ParseContext(), *m_in)) {
2129 m_keys.emplace_back();
2130 m_keys.back().push_back(std::move(pubkey_provider));
2135 if (
auto pubkey_provider = InferPubkey(pubkey,
ParseContext(), *m_in)) {
2136 m_keys.emplace_back();
2137 m_keys.back().push_back(std::move(pubkey_provider));
2144 template<
typename I> std::optional<Key> FromPKHBytes(I begin, I end)
const
2146 assert(end - begin == 20);
2149 std::copy(begin, end, hash.
begin());
2153 if (
auto pubkey_provider = InferPubkey(pubkey,
ParseContext(), *m_in)) {
2154 Key key = m_keys.
size();
2155 m_keys.emplace_back();
2156 m_keys.back().push_back(std::move(pubkey_provider));
2164 return m_script_ctx;
2170std::vector<std::unique_ptr<DescriptorImpl>>
ParseScript(uint32_t& key_exp_index, std::span<const char>& sp, ParseScriptContext ctx,
FlatSigningProvider&
out, std::string& error)
2173 Assume(ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH || ctx == ParseScriptContext::P2TR);
2174 std::vector<std::unique_ptr<DescriptorImpl>>
ret;
2175 auto expr =
Expr(sp);
2176 if (
Func(
"pk", expr)) {
2177 auto pubkeys = ParsePubkey(key_exp_index, expr, ctx,
out, error);
2178 if (pubkeys.empty()) {
2183 for (
auto& pubkey : pubkeys) {
2184 ret.emplace_back(std::make_unique<PKDescriptor>(std::move(pubkey), ctx == ParseScriptContext::P2TR));
2188 if ((ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH) &&
Func(
"pkh", expr)) {
2189 auto pubkeys = ParsePubkey(key_exp_index, expr, ctx,
out, error);
2190 if (pubkeys.empty()) {
2195 for (
auto& pubkey : pubkeys) {
2196 ret.emplace_back(std::make_unique<PKHDescriptor>(std::move(pubkey)));
2200 if (ctx == ParseScriptContext::TOP &&
Func(
"combo", expr)) {
2201 auto pubkeys = ParsePubkey(key_exp_index, expr, ctx,
out, error);
2202 if (pubkeys.empty()) {
2203 error =
strprintf(
"combo(): %s", error);
2207 for (
auto& pubkey : pubkeys) {
2208 ret.emplace_back(std::make_unique<ComboDescriptor>(std::move(pubkey)));
2211 }
else if (
Func(
"combo", expr)) {
2212 error =
"Can only have combo() at top level";
2215 const bool multi =
Func(
"multi", expr);
2216 const bool sortedmulti = !multi &&
Func(
"sortedmulti", expr);
2217 const bool multi_a = !(multi || sortedmulti) &&
Func(
"multi_a", expr);
2218 const bool sortedmulti_a = !(multi || sortedmulti || multi_a) &&
Func(
"sortedmulti_a", expr);
2219 if (((ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH) && (multi || sortedmulti)) ||
2220 (ctx == ParseScriptContext::P2TR && (multi_a || sortedmulti_a))) {
2221 auto threshold =
Expr(expr);
2223 std::vector<std::vector<std::unique_ptr<PubkeyProvider>>> providers;
2224 if (
const auto maybe_thres{ToIntegral<uint32_t>(std::string_view{threshold.begin(), threshold.end()})}) {
2225 thres = *maybe_thres;
2227 error =
strprintf(
"Multi threshold '%s' is not valid", std::string(threshold.begin(), threshold.end()));
2230 size_t script_size = 0;
2231 size_t max_providers_len = 0;
2232 while (expr.size()) {
2233 if (!
Const(
",", expr)) {
2234 error =
strprintf(
"Multi: expected ',', got '%c'", expr[0]);
2237 auto arg =
Expr(expr);
2238 auto pks = ParsePubkey(key_exp_index, arg, ctx,
out, error);
2243 script_size += pks.at(0)->GetSize() + 1;
2244 max_providers_len = std::max(max_providers_len, pks.size());
2245 providers.emplace_back(std::move(pks));
2254 }
else if (thres < 1) {
2255 error =
strprintf(
"Multisig threshold cannot be %d, must be at least 1", thres);
2257 }
else if (thres > providers.size()) {
2258 error =
strprintf(
"Multisig threshold cannot be larger than the number of keys; threshold is %d but only %u keys specified", thres, providers.size());
2261 if (ctx == ParseScriptContext::TOP) {
2262 if (providers.size() > 3) {
2263 error =
strprintf(
"Cannot have %u pubkeys in bare multisig; only at most 3 pubkeys", providers.size());
2267 if (ctx == ParseScriptContext::P2SH) {
2277 for (
auto& vec : providers) {
2278 if (vec.size() == 1) {
2279 for (
size_t i = 1; i < max_providers_len; ++i) {
2280 vec.emplace_back(vec.at(0)->Clone());
2282 }
else if (vec.size() != max_providers_len) {
2283 error =
strprintf(
"multi(): Multipath derivation paths have mismatched lengths");
2289 for (
size_t i = 0; i < max_providers_len; ++i) {
2291 std::vector<std::unique_ptr<PubkeyProvider>> pubs;
2292 pubs.reserve(providers.size());
2293 for (
auto& pub : providers) {
2294 pubs.emplace_back(std::move(pub.at(i)));
2296 if (multi || sortedmulti) {
2297 ret.emplace_back(std::make_unique<MultisigDescriptor>(thres, std::move(pubs), sortedmulti));
2299 ret.emplace_back(std::make_unique<MultiADescriptor>(thres, std::move(pubs), sortedmulti_a));
2303 }
else if (multi || sortedmulti) {
2304 error =
"Can only have multi/sortedmulti at top level, in sh(), or in wsh()";
2306 }
else if (multi_a || sortedmulti_a) {
2307 error =
"Can only have multi_a/sortedmulti_a inside tr()";
2310 if ((ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH) &&
Func(
"wpkh", expr)) {
2311 auto pubkeys = ParsePubkey(key_exp_index, expr, ParseScriptContext::P2WPKH,
out, error);
2312 if (pubkeys.empty()) {
2317 for (
auto& pubkey : pubkeys) {
2318 ret.emplace_back(std::make_unique<WPKHDescriptor>(std::move(pubkey)));
2321 }
else if (
Func(
"wpkh", expr)) {
2322 error =
"Can only have wpkh() at top level or inside sh()";
2325 if (ctx == ParseScriptContext::TOP &&
Func(
"sh", expr)) {
2326 auto descs =
ParseScript(key_exp_index, expr, ParseScriptContext::P2SH,
out, error);
2327 if (descs.empty() || expr.size())
return {};
2328 std::vector<std::unique_ptr<DescriptorImpl>>
ret;
2329 ret.reserve(descs.size());
2330 for (
auto& desc : descs) {
2331 ret.push_back(std::make_unique<SHDescriptor>(std::move(desc)));
2334 }
else if (
Func(
"sh", expr)) {
2335 error =
"Can only have sh() at top level";
2338 if ((ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH) &&
Func(
"wsh", expr)) {
2339 auto descs =
ParseScript(key_exp_index, expr, ParseScriptContext::P2WSH,
out, error);
2340 if (descs.empty() || expr.size())
return {};
2341 for (
auto& desc : descs) {
2342 ret.emplace_back(std::make_unique<WSHDescriptor>(std::move(desc)));
2345 }
else if (
Func(
"wsh", expr)) {
2346 error =
"Can only have wsh() at top level or inside sh()";
2349 if (ctx == ParseScriptContext::TOP &&
Func(
"addr", expr)) {
2352 error =
"Address is not valid";
2355 ret.emplace_back(std::make_unique<AddressDescriptor>(std::move(dest)));
2357 }
else if (
Func(
"addr", expr)) {
2358 error =
"Can only have addr() at top level";
2361 if (ctx == ParseScriptContext::TOP &&
Func(
"tr", expr)) {
2362 auto arg =
Expr(expr);
2363 auto internal_keys = ParsePubkey(key_exp_index, arg, ParseScriptContext::P2TR,
out, error);
2364 if (internal_keys.empty()) {
2368 size_t max_providers_len = internal_keys.size();
2370 std::vector<std::vector<std::unique_ptr<DescriptorImpl>>> subscripts;
2371 std::vector<int> depths;
2373 if (!
Const(
",", expr)) {
2374 error =
strprintf(
"tr: expected ',', got '%c'", expr[0]);
2380 std::vector<bool> branches;
2385 while (
Const(
"{", expr)) {
2386 branches.push_back(
false);
2393 auto sarg =
Expr(expr);
2394 subscripts.emplace_back(
ParseScript(key_exp_index, sarg, ParseScriptContext::P2TR,
out, error));
2395 if (subscripts.back().empty())
return {};
2396 max_providers_len = std::max(max_providers_len, subscripts.back().size());
2397 depths.push_back(branches.size());
2399 while (branches.size() && branches.back()) {
2400 if (!
Const(
"}", expr)) {
2401 error =
strprintf(
"tr(): expected '}' after script expression");
2404 branches.pop_back();
2407 if (branches.size() && !branches.back()) {
2408 if (!
Const(
",", expr)) {
2409 error =
strprintf(
"tr(): expected ',' after script expression");
2412 branches.back() =
true;
2414 }
while (branches.size());
2417 error =
strprintf(
"tr(): expected ')' after script expression");
2425 for (
auto& vec : subscripts) {
2426 if (vec.size() == 1) {
2427 for (
size_t i = 1; i < max_providers_len; ++i) {
2428 vec.emplace_back(vec.at(0)->Clone());
2430 }
else if (vec.size() != max_providers_len) {
2431 error =
strprintf(
"tr(): Multipath subscripts have mismatched lengths");
2436 if (internal_keys.size() > 1 && internal_keys.size() != max_providers_len) {
2437 error =
strprintf(
"tr(): Multipath internal key mismatches multipath subscripts lengths");
2441 while (internal_keys.size() < max_providers_len) {
2442 internal_keys.emplace_back(internal_keys.at(0)->Clone());
2446 for (
size_t i = 0; i < max_providers_len; ++i) {
2448 std::vector<std::unique_ptr<DescriptorImpl>> this_subs;
2449 this_subs.reserve(subscripts.size());
2450 for (
auto& subs : subscripts) {
2451 this_subs.emplace_back(std::move(subs.at(i)));
2453 ret.emplace_back(std::make_unique<TRDescriptor>(std::move(internal_keys.at(i)), std::move(this_subs), depths));
2458 }
else if (
Func(
"tr", expr)) {
2459 error =
"Can only have tr at top level";
2462 if (ctx == ParseScriptContext::TOP &&
Func(
"rawtr", expr)) {
2463 auto arg =
Expr(expr);
2465 error =
strprintf(
"rawtr(): only one key expected.");
2468 auto output_keys = ParsePubkey(key_exp_index, arg, ParseScriptContext::P2TR,
out, error);
2469 if (output_keys.empty()) {
2470 error =
strprintf(
"rawtr(): %s", error);
2474 for (
auto& pubkey : output_keys) {
2475 ret.emplace_back(std::make_unique<RawTRDescriptor>(std::move(pubkey)));
2478 }
else if (
Func(
"rawtr", expr)) {
2479 error =
"Can only have rawtr at top level";
2482 if (ctx == ParseScriptContext::TOP &&
Func(
"raw", expr)) {
2483 std::string str(expr.begin(), expr.end());
2485 error =
"Raw script is not hex";
2489 ret.emplace_back(std::make_unique<RawDescriptor>(
CScript(bytes.begin(), bytes.end())));
2491 }
else if (
Func(
"raw", expr)) {
2492 error =
"Can only have raw() at top level";
2498 KeyParser parser(&
out,
nullptr, script_ctx, key_exp_index);
2500 if (parser.m_key_parsing_error !=
"") {
2501 error = std::move(parser.m_key_parsing_error);
2505 if (ctx != ParseScriptContext::P2WSH && ctx != ParseScriptContext::P2TR) {
2506 error =
"Miniscript expressions can only be used in wsh or tr.";
2509 if (!
node->IsSane() ||
node->IsNotSatisfiable()) {
2511 auto insane_node =
node.get();
2512 if (
const auto sub =
node->FindInsaneSub()) insane_node = sub;
2513 if (
const auto str = insane_node->ToString(parser)) error = *str;
2514 if (!insane_node->IsValid()) {
2515 error +=
" is invalid";
2516 }
else if (!
node->IsSane()) {
2517 error +=
" is not sane";
2518 if (!insane_node->IsNonMalleable()) {
2519 error +=
": malleable witnesses exist";
2520 }
else if (insane_node ==
node.get() && !insane_node->NeedsSignature()) {
2521 error +=
": witnesses without signature exist";
2522 }
else if (!insane_node->CheckTimeLocksMix()) {
2523 error +=
": contains mixes of timelocks expressed in blocks and seconds";
2524 }
else if (!insane_node->CheckDuplicateKey()) {
2525 error +=
": contains duplicate public keys";
2526 }
else if (!insane_node->ValidSatisfactions()) {
2527 error +=
": needs witnesses that may exceed resource limits";
2530 error +=
" is not satisfiable";
2537 key_exp_index += parser.m_keys.size();
2540 size_t num_multipath = std::max_element(parser.m_keys.begin(), parser.m_keys.end(),
2541 [](
const std::vector<std::unique_ptr<PubkeyProvider>>& a,
const std::vector<std::unique_ptr<PubkeyProvider>>& b) {
2542 return a.size() < b.size();
2545 for (
auto& vec : parser.m_keys) {
2546 if (vec.size() == 1) {
2547 for (
size_t i = 1; i < num_multipath; ++i) {
2548 vec.emplace_back(vec.at(0)->Clone());
2550 }
else if (vec.size() != num_multipath) {
2551 error =
strprintf(
"Miniscript: Multipath derivation paths have mismatched lengths");
2557 for (
size_t i = 0; i < num_multipath; ++i) {
2559 std::vector<std::unique_ptr<PubkeyProvider>> pubs;
2560 pubs.reserve(parser.m_keys.size());
2561 for (
auto& pub : parser.m_keys) {
2562 pubs.emplace_back(std::move(pub.at(i)));
2564 ret.emplace_back(std::make_unique<MiniscriptDescriptor>(std::move(pubs),
node->Clone()));
2569 if (ctx == ParseScriptContext::P2SH) {
2570 error =
"A function is needed within P2SH";
2572 }
else if (ctx == ParseScriptContext::P2WSH) {
2573 error =
"A function is needed within P2WSH";
2576 error =
strprintf(
"'%s' is not a valid descriptor function", std::string(expr.begin(), expr.end()));
2583 if (!match)
return {};
2584 std::vector<std::unique_ptr<PubkeyProvider>> keys;
2585 keys.reserve(match->second.size());
2586 for (
const auto keyspan : match->second) {
2587 if (keyspan.size() != 32)
return {};
2588 auto key = InferXOnlyPubkey(
XOnlyPubKey{keyspan}, ctx, provider);
2589 if (!key)
return {};
2590 keys.push_back(std::move(key));
2592 return std::make_unique<MultiADescriptor>(match->first, std::move(keys));
2600 return std::make_unique<PKDescriptor>(InferXOnlyPubkey(key, ctx, provider),
true);
2603 if (ctx == ParseScriptContext::P2TR) {
2604 auto ret = InferMultiA(
script, ctx, provider);
2608 std::vector<std::vector<unsigned char>>
data;
2611 if (txntype ==
TxoutType::PUBKEY && (ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH)) {
2613 if (
auto pubkey_provider = InferPubkey(pubkey, ctx, provider)) {
2614 return std::make_unique<PKDescriptor>(std::move(pubkey_provider));
2617 if (txntype ==
TxoutType::PUBKEYHASH && (ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH)) {
2621 if (provider.
GetPubKey(keyid, pubkey)) {
2622 if (
auto pubkey_provider = InferPubkey(pubkey, ctx, provider)) {
2623 return std::make_unique<PKHDescriptor>(std::move(pubkey_provider));
2631 if (provider.
GetPubKey(keyid, pubkey)) {
2632 if (
auto pubkey_provider = InferPubkey(pubkey, ParseScriptContext::P2WPKH, provider)) {
2633 return std::make_unique<WPKHDescriptor>(std::move(pubkey_provider));
2637 if (txntype ==
TxoutType::MULTISIG && (ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH)) {
2639 std::vector<std::unique_ptr<PubkeyProvider>> providers;
2640 for (
size_t i = 1; i + 1 <
data.size(); ++i) {
2642 if (
auto pubkey_provider = InferPubkey(pubkey, ctx, provider)) {
2643 providers.push_back(std::move(pubkey_provider));
2649 if (ok)
return std::make_unique<MultisigDescriptor>((
int)
data[0][0], std::move(providers));
2655 if (provider.
GetCScript(scriptid, subscript)) {
2656 auto sub = InferScript(subscript, ParseScriptContext::P2SH, provider);
2657 if (sub)
return std::make_unique<SHDescriptor>(std::move(sub));
2663 if (provider.
GetCScript(scriptid, subscript)) {
2664 auto sub = InferScript(subscript, ParseScriptContext::P2WSH, provider);
2665 if (sub)
return std::make_unique<WSHDescriptor>(std::move(sub));
2680 std::vector<std::unique_ptr<DescriptorImpl>> subscripts;
2681 std::vector<int> depths;
2682 for (
const auto& [depth,
script, leaf_ver] : *tree) {
2683 std::unique_ptr<DescriptorImpl> subdesc;
2685 subdesc = InferScript(
CScript(
script.begin(),
script.end()), ParseScriptContext::P2TR, provider);
2691 subscripts.push_back(std::move(subdesc));
2692 depths.push_back(depth);
2696 auto key = InferXOnlyPubkey(tap.
internal_key, ParseScriptContext::P2TR, provider);
2697 return std::make_unique<TRDescriptor>(std::move(key), std::move(subscripts), std::move(depths));
2703 auto key = InferXOnlyPubkey(pubkey, ParseScriptContext::P2TR, provider);
2705 return std::make_unique<RawTRDescriptor>(std::move(key));
2710 if (ctx == ParseScriptContext::P2WSH || ctx == ParseScriptContext::P2TR) {
2712 KeyParser parser(
nullptr, &provider, script_ctx);
2715 std::vector<std::unique_ptr<PubkeyProvider>> keys;
2716 keys.reserve(parser.m_keys.size());
2717 for (
auto& key : parser.m_keys) {
2718 keys.emplace_back(std::move(key.at(0)));
2720 return std::make_unique<MiniscriptDescriptor>(std::move(keys), std::move(
node));
2726 if (ctx != ParseScriptContext::TOP)
return nullptr;
2731 return std::make_unique<AddressDescriptor>(std::move(dest));
2735 return std::make_unique<RawDescriptor>(
script);
2742bool CheckChecksum(std::span<const char>& sp,
bool require_checksum, std::string& error, std::string* out_checksum =
nullptr)
2744 auto check_split =
Split(sp,
'#');
2745 if (check_split.size() > 2) {
2746 error =
"Multiple '#' symbols";
2749 if (check_split.size() == 1 && require_checksum){
2750 error =
"Missing checksum";
2753 if (check_split.size() == 2) {
2754 if (check_split[1].size() != 8) {
2755 error =
strprintf(
"Expected 8 character checksum, not %u characters", check_split[1].size());
2759 auto checksum = DescriptorChecksum(check_split[0]);
2760 if (checksum.empty()) {
2761 error =
"Invalid characters in payload";
2764 if (check_split.size() == 2) {
2765 if (!std::equal(checksum.begin(), checksum.end(), check_split[1].begin())) {
2766 error =
strprintf(
"Provided checksum '%s' does not match computed checksum '%s'", std::string(check_split[1].begin(), check_split[1].end()), checksum);
2770 if (out_checksum) *out_checksum = std::move(checksum);
2771 sp = check_split[0];
2777 std::span<const char> sp{descriptor};
2779 uint32_t key_exp_index = 0;
2781 if (sp.empty() && !
ret.empty()) {
2782 std::vector<std::unique_ptr<Descriptor>> descs;
2783 descs.reserve(
ret.size());
2784 for (
auto& r :
ret) {
2785 descs.emplace_back(std::unique_ptr<Descriptor>(std::move(r)));
2796 std::span<const char> sp{descriptor};
2803 return InferScript(
script, ParseScriptContext::TOP, provider);
2808 std::string desc_str = desc.
ToString(
true);
2822 xpubs[der_index] = xpub;
2842 const auto& der_it = key_exp_it->second.find(der_index);
2843 if (der_it == key_exp_it->second.end())
return false;
2844 xpub = der_it->second;
2862 if (xpub != parent_xpub_pair.second) {
2863 throw std::runtime_error(std::string(__func__) +
": New cached parent xpub does not match already cached parent xpub");
2871 for (
const auto& derived_xpub_pair : derived_xpub_map_pair.second) {
2874 if (xpub != derived_xpub_pair.second) {
2875 throw std::runtime_error(std::string(__func__) +
": New cached derived xpub does not match already cached derived xpub");
2879 CacheDerivedExtPubKey(derived_xpub_map_pair.first, derived_xpub_pair.first, derived_xpub_pair.second);
2880 diff.
CacheDerivedExtPubKey(derived_xpub_map_pair.first, derived_xpub_pair.first, derived_xpub_pair.second);
2886 if (xpub != lh_xpub_pair.second) {
2887 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)
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.
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.
void ForEachNode(const Node< Key > &root, Fn &&fn)
Unordered traversal of a miniscript node tree.
NodeRef< typename Ctx::Key > FromScript(const CScript &script, const Ctx &ctx)
std::unique_ptr< const Node< Key > > NodeRef
@ 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 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.
A node in a miniscript expression.
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.