93uint64_t
PolyMod(uint64_t c,
int val)
96 c = ((c & 0x7ffffffff) << 5) ^ val;
97 if (c0 & 1) c ^= 0xf5dee51989;
98 if (c0 & 2) c ^= 0xa9fdca3312;
99 if (c0 & 4) c ^= 0x1bab10e32d;
100 if (c0 & 8) c ^= 0x3706b1677a;
101 if (c0 & 16) c ^= 0x644d626ffd;
105std::string DescriptorChecksum(
const std::span<const char>& span)
120 static const std::string INPUT_CHARSET =
121 "0123456789()[],'/*abcdefgh@:$%{}"
122 "IJKLMNOPQRSTUVWXYZ&+-.;<=>?!^_|~"
123 "ijklmnopqrstuvwxyzABCDEFGH`#\"\\ ";
126 static const std::string CHECKSUM_CHARSET =
"qpzry9x8gf2tvdw0s3jn54khce6mua7l";
131 for (
auto ch : span) {
132 auto pos = INPUT_CHARSET.find(ch);
133 if (pos == std::string::npos)
return "";
135 cls = cls * 3 + (pos >> 5);
136 if (++clscount == 3) {
143 if (clscount > 0) c =
PolyMod(c, cls);
144 for (
int j = 0; j < 8; ++j) c =
PolyMod(c, 0);
147 std::string
ret(8,
' ');
148 for (
int j = 0; j < 8; ++j)
ret[j] = CHECKSUM_CHARSET[(c >> (5 * (7 - j))) & 31];
152std::string AddChecksum(
const std::string& str) {
return str +
"#" + DescriptorChecksum(str); }
158typedef std::vector<uint32_t> KeyPath;
166 uint32_t m_expr_index;
169 explicit PubkeyProvider(uint32_t exp_index) : m_expr_index(exp_index) {}
171 virtual ~PubkeyProvider() =
default;
176 bool operator<(PubkeyProvider& other)
const {
182 other.GetPubKey(0, dummy, b, dummy_info);
195 virtual bool IsRange()
const = 0;
198 virtual size_t GetSize()
const = 0;
200 enum class StringType {
206 virtual std::string
ToString(StringType type=StringType::PUBLIC)
const = 0;
220 virtual std::optional<CPubKey> GetRootPubKey()
const = 0;
222 virtual std::optional<CExtPubKey> GetRootExtPubKey()
const = 0;
225 virtual std::unique_ptr<PubkeyProvider> Clone()
const = 0;
228class OriginPubkeyProvider final :
public PubkeyProvider
231 std::unique_ptr<PubkeyProvider> m_provider;
234 std::string OriginString(StringType type,
bool normalized=
false)
const
237 bool use_apostrophe = (!normalized && m_apostrophe) || type == StringType::COMPAT;
242 OriginPubkeyProvider(uint32_t exp_index,
KeyOriginInfo info, std::unique_ptr<PubkeyProvider> provider,
bool apostrophe) : PubkeyProvider(exp_index), m_origin(
std::move(info)), m_provider(
std::move(provider)), m_apostrophe(apostrophe) {}
245 if (!m_provider->GetPubKey(pos, arg, key, info, read_cache, write_cache))
return false;
246 std::copy(std::begin(m_origin.fingerprint), std::end(m_origin.fingerprint), info.
fingerprint);
247 info.
path.insert(info.
path.begin(), m_origin.path.begin(), m_origin.path.end());
250 bool IsRange()
const override {
return m_provider->IsRange(); }
251 size_t GetSize()
const override {
return m_provider->GetSize(); }
252 std::string
ToString(StringType type)
const override {
return "[" + OriginString(type) +
"]" + m_provider->ToString(type); }
256 if (!m_provider->ToPrivateString(arg, sub))
return false;
257 ret =
"[" + OriginString(StringType::PUBLIC) +
"]" + std::move(sub);
263 if (!m_provider->ToNormalizedString(arg, sub, cache))
return false;
269 ret =
"[" + OriginString(StringType::PUBLIC,
true) + std::move(sub);
271 ret =
"[" + OriginString(StringType::PUBLIC,
true) +
"]" + std::move(sub);
277 return m_provider->GetPrivKey(pos, arg, key);
279 std::optional<CPubKey> GetRootPubKey()
const override
281 return m_provider->GetRootPubKey();
283 std::optional<CExtPubKey> GetRootExtPubKey()
const override
285 return m_provider->GetRootExtPubKey();
287 std::unique_ptr<PubkeyProvider> Clone()
const override
289 return std::make_unique<OriginPubkeyProvider>(m_expr_index, m_origin, m_provider->Clone(), m_apostrophe);
294class ConstPubkeyProvider final :
public PubkeyProvider
300 ConstPubkeyProvider(uint32_t exp_index,
const CPubKey& pubkey,
bool xonly) : PubkeyProvider(exp_index), m_pubkey(pubkey), m_xonly(xonly) {}
305 CKeyID keyid = m_pubkey.GetID();
309 bool IsRange()
const override {
return false; }
310 size_t GetSize()
const override {
return m_pubkey.size(); }
311 std::string
ToString(StringType type)
const override {
return m_xonly ?
HexStr(m_pubkey).substr(2) :
HexStr(m_pubkey); }
315 if (!GetPrivKey(0, arg, key))
return false;
327 arg.
GetKey(m_pubkey.GetID(), key);
329 std::optional<CPubKey> GetRootPubKey()
const override
333 std::optional<CExtPubKey> GetRootExtPubKey()
const override
337 std::unique_ptr<PubkeyProvider> Clone()
const override
339 return std::make_unique<ConstPubkeyProvider>(m_expr_index, m_pubkey, m_xonly);
343enum class DeriveType {
350class BIP32PubkeyProvider final :
public PubkeyProvider
362 if (!arg.
GetKey(m_root_extkey.pubkey.GetID(), key))
return false;
363 ret.nDepth = m_root_extkey.nDepth;
364 std::copy(m_root_extkey.vchFingerprint, m_root_extkey.vchFingerprint +
sizeof(
ret.vchFingerprint),
ret.vchFingerprint);
365 ret.nChild = m_root_extkey.nChild;
366 ret.chaincode = m_root_extkey.chaincode;
374 if (!GetExtKey(arg, xprv))
return false;
375 for (
auto entry : m_path) {
376 if (!xprv.
Derive(xprv, entry))
return false;
378 last_hardened = xprv;
384 bool IsHardened()
const
386 if (m_derive == DeriveType::HARDENED)
return true;
387 for (
auto entry : m_path) {
388 if (entry >> 31)
return true;
394 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) {}
395 bool IsRange()
const override {
return m_derive != DeriveType::NO; }
396 size_t GetSize()
const override {
return 33; }
401 CKeyID keyid = m_root_extkey.pubkey.GetID();
403 parent_info.
path = m_path;
407 if (m_derive == DeriveType::UNHARDENED) final_info_out_tmp.
path.push_back((uint32_t)pos);
408 if (m_derive == DeriveType::HARDENED) final_info_out_tmp.
path.push_back(((uint32_t)pos) | 0x80000000L);
416 if (!read_cache->GetCachedDerivedExtPubKey(m_expr_index, pos, final_extkey)) {
417 if (m_derive == DeriveType::HARDENED)
return false;
419 if (!read_cache->GetCachedParentExtPubKey(m_expr_index, parent_extkey))
return false;
420 final_extkey = parent_extkey;
421 if (m_derive == DeriveType::UNHARDENED) der = parent_extkey.
Derive(final_extkey, pos);
423 }
else if (IsHardened()) {
426 if (!GetDerivedExtKey(arg, xprv, lh_xprv))
return false;
427 parent_extkey = xprv.
Neuter();
428 if (m_derive == DeriveType::UNHARDENED) der = xprv.
Derive(xprv, pos);
429 if (m_derive == DeriveType::HARDENED) der = xprv.
Derive(xprv, pos | 0x80000000UL);
430 final_extkey = xprv.
Neuter();
432 last_hardened_extkey = lh_xprv.
Neuter();
435 for (
auto entry : m_path) {
436 if (!parent_extkey.
Derive(parent_extkey, entry))
return false;
438 final_extkey = parent_extkey;
439 if (m_derive == DeriveType::UNHARDENED) der = parent_extkey.
Derive(final_extkey, pos);
440 assert(m_derive != DeriveType::HARDENED);
442 if (!der)
return false;
444 final_info_out = final_info_out_tmp;
445 key_out = final_extkey.
pubkey;
449 if (m_derive != DeriveType::HARDENED) {
450 write_cache->CacheParentExtPubKey(m_expr_index, parent_extkey);
453 write_cache->CacheLastHardenedExtPubKey(m_expr_index, last_hardened_extkey);
455 }
else if (final_info_out.
path.size() > 0) {
456 write_cache->CacheDerivedExtPubKey(m_expr_index, pos, final_extkey);
462 std::string
ToString(StringType type,
bool normalized)
const
465 const bool use_apostrophe = (!normalized && m_apostrophe) || type == StringType::COMPAT;
469 if (m_derive == DeriveType::HARDENED)
ret += use_apostrophe ?
'\'' :
'h';
473 std::string
ToString(StringType type=StringType::PUBLIC)
const override
480 if (!GetExtKey(arg, key))
return false;
484 if (m_derive == DeriveType::HARDENED)
out += m_apostrophe ?
'\'' :
'h';
490 if (m_derive == DeriveType::HARDENED) {
496 int i = (int)m_path.size() - 1;
497 for (; i >= 0; --i) {
498 if (m_path.at(i) >> 31) {
510 for (;
k <= i; ++
k) {
512 origin.
path.push_back(m_path.at(
k));
516 for (;
k < (int)m_path.size(); ++
k) {
517 end_path.push_back(m_path.at(
k));
520 CKeyID id = m_root_extkey.pubkey.GetID();
521 std::copy(
id.begin(),
id.begin() + 4, origin.
fingerprint);
526 if (cache !=
nullptr) {
532 if (!GetDerivedExtKey(arg, xprv, lh_xprv))
return false;
542 assert(m_derive == DeriveType::UNHARDENED);
550 if (!GetDerivedExtKey(arg, extkey, dummy))
return false;
551 if (m_derive == DeriveType::UNHARDENED && !extkey.
Derive(extkey, pos))
return false;
552 if (m_derive == DeriveType::HARDENED && !extkey.
Derive(extkey, pos | 0x80000000UL))
return false;
556 std::optional<CPubKey> GetRootPubKey()
const override
560 std::optional<CExtPubKey> GetRootExtPubKey()
const override
562 return m_root_extkey;
564 std::unique_ptr<PubkeyProvider> Clone()
const override
566 return std::make_unique<BIP32PubkeyProvider>(m_expr_index, m_root_extkey, m_path, m_derive, m_apostrophe);
575 const std::vector<std::unique_ptr<PubkeyProvider>> m_pubkey_args;
577 const std::string m_name;
583 const std::vector<std::unique_ptr<DescriptorImpl>> m_subdescriptor_args;
586 virtual std::string ToStringExtra()
const {
return ""; }
598 virtual std::vector<CScript> MakeScripts(
const std::vector<CPubKey>& pubkeys, std::span<const CScript> scripts,
FlatSigningProvider&
out)
const = 0;
601 DescriptorImpl(std::vector<std::unique_ptr<PubkeyProvider>> pubkeys,
const std::string&
name) : m_pubkey_args(
std::move(pubkeys)), m_name(
name), m_subdescriptor_args() {}
602 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))) {}
603 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)) {}
605 enum class StringType
616 for (
const auto& arg : m_subdescriptor_args) {
617 if (!arg->IsSolvable())
return false;
625 for (
const auto& pubkey : m_pubkey_args) {
626 if (pubkey->IsRange())
return true;
628 for (
const auto& arg : m_subdescriptor_args) {
629 if (arg->IsRange())
return true;
638 for (
const auto& scriptarg : m_subdescriptor_args) {
639 if (pos++)
ret +=
",";
641 if (!scriptarg->ToStringHelper(arg, tmp, type, cache))
return false;
650 std::string extra = ToStringExtra();
651 size_t pos = extra.size() > 0 ? 1 : 0;
652 std::string
ret = m_name +
"(" + extra;
653 for (
const auto& pubkey : m_pubkey_args) {
654 if (pos++)
ret +=
",";
657 case StringType::NORMALIZED:
658 if (!pubkey->ToNormalizedString(*arg, tmp, cache))
return false;
660 case StringType::PRIVATE:
661 if (!pubkey->ToPrivateString(*arg, tmp))
return false;
663 case StringType::PUBLIC:
664 tmp = pubkey->ToString();
666 case StringType::COMPAT:
667 tmp = pubkey->ToString(PubkeyProvider::StringType::COMPAT);
672 std::string subscript;
673 if (!ToStringSubScriptHelper(arg, subscript, type, cache))
return false;
674 if (pos && subscript.size())
ret +=
',';
675 out = std::move(
ret) + std::move(subscript) +
")";
679 std::string
ToString(
bool compat_format)
const final
682 ToStringHelper(
nullptr,
ret, compat_format ? StringType::COMPAT : StringType::PUBLIC);
683 return AddChecksum(
ret);
688 bool ret = ToStringHelper(&arg,
out, StringType::PRIVATE);
695 bool ret = ToStringHelper(&arg,
out, StringType::NORMALIZED, cache);
703 std::vector<std::pair<CPubKey, KeyOriginInfo>> entries;
704 entries.reserve(m_pubkey_args.size());
707 for (
const auto& p : m_pubkey_args) {
708 entries.emplace_back();
709 if (!p->GetPubKey(pos, arg, entries.back().first, entries.back().second, read_cache, write_cache))
return false;
711 std::vector<CScript> subscripts;
713 for (
const auto& subarg : m_subdescriptor_args) {
714 std::vector<CScript> outscripts;
715 if (!subarg->ExpandHelper(pos, arg, read_cache, outscripts, subprovider, write_cache))
return false;
716 assert(outscripts.size() == 1);
717 subscripts.emplace_back(std::move(outscripts[0]));
719 out.Merge(std::move(subprovider));
721 std::vector<CPubKey> pubkeys;
722 pubkeys.reserve(entries.size());
723 for (
auto& entry : entries) {
724 pubkeys.push_back(entry.first);
725 out.origins.emplace(entry.first.GetID(), std::make_pair<CPubKey, KeyOriginInfo>(
CPubKey(entry.first), std::move(entry.second)));
728 output_scripts = MakeScripts(pubkeys, std::span{subscripts},
out);
734 return ExpandHelper(pos, provider,
nullptr, output_scripts,
out, write_cache);
745 for (
const auto& p : m_pubkey_args) {
747 if (!p->GetPrivKey(pos, provider, key))
continue;
750 for (
const auto& arg : m_subdescriptor_args) {
751 arg->ExpandPrivate(pos, provider,
out);
755 std::optional<OutputType>
GetOutputType()
const override {
return std::nullopt; }
757 std::optional<int64_t>
ScriptSize()
const override {
return {}; }
764 virtual std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const {
return {}; }
771 void GetPubKeys(std::set<CPubKey>& pubkeys, std::set<CExtPubKey>& ext_pubs)
const override
773 for (
const auto& p : m_pubkey_args) {
774 std::optional<CPubKey> pub = p->GetRootPubKey();
775 if (pub) pubkeys.insert(*pub);
776 std::optional<CExtPubKey> ext_pub = p->GetRootExtPubKey();
777 if (ext_pub) ext_pubs.insert(*ext_pub);
779 for (
const auto& arg : m_subdescriptor_args) {
780 arg->GetPubKeys(pubkeys, ext_pubs);
784 virtual std::unique_ptr<DescriptorImpl> Clone()
const = 0;
788class AddressDescriptor final :
public DescriptorImpl
792 std::string ToStringExtra()
const override {
return EncodeDestination(m_destination); }
795 AddressDescriptor(
CTxDestination destination) : DescriptorImpl({},
"addr"), m_destination(std::move(destination)) {}
796 bool IsSolvable() const final {
return false; }
802 bool IsSingleType() const final {
return true; }
803 bool ToPrivateString(
const SigningProvider& arg, std::string&
out)
const final {
return false; }
806 std::unique_ptr<DescriptorImpl> Clone()
const override
808 return std::make_unique<AddressDescriptor>(m_destination);
813class RawDescriptor final :
public DescriptorImpl
817 std::string ToStringExtra()
const override {
return HexStr(m_script); }
818 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>&, std::span<const CScript>,
FlatSigningProvider&)
const override {
return Vector(m_script); }
821 bool IsSolvable() const final {
return false; }
829 bool IsSingleType() const final {
return true; }
830 bool ToPrivateString(
const SigningProvider& arg, std::string&
out)
const final {
return false; }
832 std::optional<int64_t> ScriptSize()
const override {
return m_script.size(); }
834 std::unique_ptr<DescriptorImpl> Clone()
const override
836 return std::make_unique<RawDescriptor>(m_script);
841class PKDescriptor final :
public DescriptorImpl
846 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>& keys, std::span<const CScript>,
FlatSigningProvider&)
const override
856 PKDescriptor(std::unique_ptr<PubkeyProvider> prov,
bool xonly =
false) : DescriptorImpl(
Vector(
std::move(prov)),
"pk"), m_xonly(xonly) {}
857 bool IsSingleType() const final {
return true; }
859 std::optional<int64_t> ScriptSize()
const override {
860 return 1 + (m_xonly ? 32 : m_pubkey_args[0]->GetSize()) + 1;
863 std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const override {
864 const auto ecdsa_sig_size = use_max_sig ? 72 : 71;
865 return 1 + (m_xonly ? 65 : ecdsa_sig_size);
868 std::optional<int64_t> MaxSatisfactionWeight(
bool use_max_sig)
const override {
872 std::optional<int64_t> MaxSatisfactionElems()
const override {
return 1; }
874 std::unique_ptr<DescriptorImpl> Clone()
const override
876 return std::make_unique<PKDescriptor>(m_pubkey_args.at(0)->Clone(), m_xonly);
881class PKHDescriptor final :
public DescriptorImpl
884 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>& keys, std::span<const CScript>,
FlatSigningProvider&
out)
const override
886 CKeyID id = keys[0].GetID();
887 out.pubkeys.emplace(
id, keys[0]);
891 PKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(
Vector(
std::move(prov)),
"pkh") {}
893 bool IsSingleType() const final {
return true; }
895 std::optional<int64_t> ScriptSize()
const override {
return 1 + 1 + 1 + 20 + 1 + 1; }
897 std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const override {
898 const auto sig_size = use_max_sig ? 72 : 71;
899 return 1 +
sig_size + 1 + m_pubkey_args[0]->GetSize();
902 std::optional<int64_t> MaxSatisfactionWeight(
bool use_max_sig)
const override {
906 std::optional<int64_t> MaxSatisfactionElems()
const override {
return 2; }
908 std::unique_ptr<DescriptorImpl> Clone()
const override
910 return std::make_unique<PKHDescriptor>(m_pubkey_args.at(0)->Clone());
915class WPKHDescriptor final :
public DescriptorImpl
918 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>& keys, std::span<const CScript>,
FlatSigningProvider&
out)
const override
920 CKeyID id = keys[0].GetID();
921 out.pubkeys.emplace(
id, keys[0]);
925 WPKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(
Vector(
std::move(prov)),
"wpkh") {}
927 bool IsSingleType() const final {
return true; }
929 std::optional<int64_t> ScriptSize()
const override {
return 1 + 1 + 20; }
931 std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const override {
932 const auto sig_size = use_max_sig ? 72 : 71;
936 std::optional<int64_t> MaxSatisfactionWeight(
bool use_max_sig)
const override {
937 return MaxSatSize(use_max_sig);
940 std::optional<int64_t> MaxSatisfactionElems()
const override {
return 2; }
942 std::unique_ptr<DescriptorImpl> Clone()
const override
944 return std::make_unique<WPKHDescriptor>(m_pubkey_args.at(0)->Clone());
949class ComboDescriptor final :
public DescriptorImpl
952 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>& keys, std::span<const CScript>,
FlatSigningProvider&
out)
const override
954 std::vector<CScript>
ret;
955 CKeyID id = keys[0].GetID();
956 out.pubkeys.emplace(
id, keys[0]);
959 if (keys[0].IsCompressed()) {
962 ret.emplace_back(p2wpkh);
968 ComboDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(
Vector(
std::move(prov)),
"combo") {}
969 bool IsSingleType() const final {
return false; }
970 std::unique_ptr<DescriptorImpl> Clone()
const override
972 return std::make_unique<ComboDescriptor>(m_pubkey_args.at(0)->Clone());
977class MultisigDescriptor final :
public DescriptorImpl
979 const int m_threshold;
982 std::string ToStringExtra()
const override {
return strprintf(
"%i", m_threshold); }
983 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>& keys, std::span<const CScript>,
FlatSigningProvider&)
const override {
985 std::vector<CPubKey> sorted_keys(keys);
986 std::sort(sorted_keys.begin(), sorted_keys.end());
992 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) {}
993 bool IsSingleType() const final {
return true; }
995 std::optional<int64_t> ScriptSize()
const override {
996 const auto n_keys = m_pubkey_args.size();
997 auto op = [](int64_t acc,
const std::unique_ptr<PubkeyProvider>&
pk) {
return acc + 1 +
pk->GetSize();};
998 const auto pubkeys_size{std::accumulate(m_pubkey_args.begin(), m_pubkey_args.end(), int64_t{0}, op)};
1002 std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const override {
1003 const auto sig_size = use_max_sig ? 72 : 71;
1004 return (1 + (1 +
sig_size) * m_threshold);
1007 std::optional<int64_t> MaxSatisfactionWeight(
bool use_max_sig)
const override {
1011 std::optional<int64_t> MaxSatisfactionElems()
const override {
return 1 + m_threshold; }
1013 std::unique_ptr<DescriptorImpl> Clone()
const override
1015 std::vector<std::unique_ptr<PubkeyProvider>> providers;
1016 providers.reserve(m_pubkey_args.size());
1017 std::transform(m_pubkey_args.begin(), m_pubkey_args.end(), providers.begin(), [](
const std::unique_ptr<PubkeyProvider>& p) { return p->Clone(); });
1018 return std::make_unique<MultisigDescriptor>(m_threshold, std::move(providers), m_sorted);
1023class MultiADescriptor final :
public DescriptorImpl
1025 const int m_threshold;
1026 const bool m_sorted;
1028 std::string ToStringExtra()
const override {
return strprintf(
"%i", m_threshold); }
1029 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>& keys, std::span<const CScript>,
FlatSigningProvider&)
const override {
1031 std::vector<XOnlyPubKey> xkeys;
1032 xkeys.reserve(keys.size());
1033 for (
const auto& key : keys) xkeys.emplace_back(key);
1034 if (m_sorted) std::sort(xkeys.begin(), xkeys.end());
1036 for (
size_t i = 1; i < keys.size(); ++i) {
1043 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) {}
1044 bool IsSingleType() const final {
return true; }
1046 std::optional<int64_t> ScriptSize()
const override {
1047 const auto n_keys = m_pubkey_args.size();
1051 std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const override {
1052 return (1 + 65) * m_threshold + (m_pubkey_args.size() - m_threshold);
1055 std::optional<int64_t> MaxSatisfactionElems()
const override {
return m_pubkey_args.size(); }
1057 std::unique_ptr<DescriptorImpl> Clone()
const override
1059 std::vector<std::unique_ptr<PubkeyProvider>> providers;
1060 providers.reserve(m_pubkey_args.size());
1061 for (
const auto& arg : m_pubkey_args) {
1062 providers.push_back(arg->Clone());
1064 return std::make_unique<MultiADescriptor>(m_threshold, std::move(providers), m_sorted);
1069class SHDescriptor final :
public DescriptorImpl
1072 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>&, std::span<const CScript> scripts,
FlatSigningProvider&
out)
const override
1075 if (
ret.size())
out.scripts.emplace(
CScriptID(scripts[0]), scripts[0]);
1082 SHDescriptor(std::unique_ptr<DescriptorImpl> desc) : DescriptorImpl({}, std::move(desc),
"sh") {}
1086 assert(m_subdescriptor_args.size() == 1);
1090 bool IsSingleType() const final {
return true; }
1092 std::optional<int64_t> ScriptSize()
const override {
return 1 + 1 + 20 + 1; }
1094 std::optional<int64_t> MaxSatisfactionWeight(
bool use_max_sig)
const override {
1095 if (
const auto sat_size = m_subdescriptor_args[0]->MaxSatSize(use_max_sig)) {
1096 if (
const auto subscript_size = m_subdescriptor_args[0]->ScriptSize()) {
1100 if (
IsSegwit())
return subscript_weight + *sat_size;
1107 std::optional<int64_t> MaxSatisfactionElems()
const override {
1108 if (
const auto sub_elems = m_subdescriptor_args[0]->MaxSatisfactionElems())
return 1 + *sub_elems;
1112 std::unique_ptr<DescriptorImpl> Clone()
const override
1114 return std::make_unique<SHDescriptor>(m_subdescriptor_args.at(0)->Clone());
1119class WSHDescriptor final :
public DescriptorImpl
1122 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>&, std::span<const CScript> scripts,
FlatSigningProvider&
out)
const override
1125 if (
ret.size())
out.scripts.emplace(
CScriptID(scripts[0]), scripts[0]);
1129 WSHDescriptor(std::unique_ptr<DescriptorImpl> desc) : DescriptorImpl({}, std::move(desc),
"wsh") {}
1131 bool IsSingleType() const final {
return true; }
1133 std::optional<int64_t> ScriptSize()
const override {
return 1 + 1 + 32; }
1135 std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const override {
1136 if (
const auto sat_size = m_subdescriptor_args[0]->MaxSatSize(use_max_sig)) {
1137 if (
const auto subscript_size = m_subdescriptor_args[0]->ScriptSize()) {
1144 std::optional<int64_t> MaxSatisfactionWeight(
bool use_max_sig)
const override {
1145 return MaxSatSize(use_max_sig);
1148 std::optional<int64_t> MaxSatisfactionElems()
const override {
1149 if (
const auto sub_elems = m_subdescriptor_args[0]->MaxSatisfactionElems())
return 1 + *sub_elems;
1153 std::unique_ptr<DescriptorImpl> Clone()
const override
1155 return std::make_unique<WSHDescriptor>(m_subdescriptor_args.at(0)->Clone());
1160class TRDescriptor final :
public DescriptorImpl
1162 std::vector<int> m_depths;
1164 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>& keys, std::span<const CScript> scripts,
FlatSigningProvider&
out)
const override
1167 assert(m_depths.size() == scripts.size());
1168 for (
size_t pos = 0; pos < m_depths.size(); ++pos) {
1172 assert(keys.size() == 1);
1174 if (!xpk.IsFullyValid())
return {};
1177 out.tr_trees[output] = builder;
1178 out.pubkeys.emplace(keys[0].GetID(), keys[0]);
1183 if (m_depths.empty())
return true;
1184 std::vector<bool> path;
1185 for (
size_t pos = 0; pos < m_depths.size(); ++pos) {
1186 if (pos)
ret +=
',';
1187 while ((
int)path.size() <= m_depths[pos]) {
1188 if (path.size())
ret +=
'{';
1189 path.push_back(
false);
1192 if (!m_subdescriptor_args[pos]->ToStringHelper(arg, tmp, type, cache))
return false;
1194 while (!path.empty() && path.back()) {
1195 if (path.size() > 1)
ret +=
'}';
1198 if (!path.empty()) path.back() =
true;
1203 TRDescriptor(std::unique_ptr<PubkeyProvider> internal_key, std::vector<std::unique_ptr<DescriptorImpl>> descs, std::vector<int> depths) :
1204 DescriptorImpl(
Vector(
std::move(internal_key)),
std::move(descs),
"tr"), m_depths(
std::move(depths))
1206 assert(m_subdescriptor_args.size() == m_depths.size());
1209 bool IsSingleType() const final {
return true; }
1211 std::optional<int64_t> ScriptSize()
const override {
return 1 + 1 + 32; }
1213 std::optional<int64_t> MaxSatisfactionWeight(
bool)
const override {
1218 std::optional<int64_t> MaxSatisfactionElems()
const override {
1223 std::unique_ptr<DescriptorImpl> Clone()
const override
1225 std::vector<std::unique_ptr<DescriptorImpl>> subdescs;
1226 subdescs.reserve(m_subdescriptor_args.size());
1227 std::transform(m_subdescriptor_args.begin(), m_subdescriptor_args.end(), subdescs.begin(), [](
const std::unique_ptr<DescriptorImpl>& d) { return d->Clone(); });
1228 return std::make_unique<TRDescriptor>(m_pubkey_args.at(0)->Clone(), std::move(subdescs), m_depths);
1242 const std::vector<CPubKey>& m_keys;
1249 uint160 GetHash160(uint32_t key)
const {
1253 return m_keys[key].GetID();
1259 std::vector<unsigned char> ToPKBytes(uint32_t key)
const {
1262 return {m_keys[key].begin(), m_keys[key].end()};
1265 return {xonly_pubkey.
begin(), xonly_pubkey.end()};
1268 std::vector<unsigned char> ToPKHBytes(uint32_t key)
const {
1269 auto id = GetHash160(key);
1270 return {
id.begin(),
id.end()};
1281 const std::vector<std::unique_ptr<PubkeyProvider>>& m_pubkeys;
1287 : m_arg(arg), m_pubkeys(pubkeys), m_private(priv) {}
1289 std::optional<std::string>
ToString(uint32_t key)
const
1293 if (!m_pubkeys[key]->ToPrivateString(*m_arg,
ret))
return {};
1295 ret = m_pubkeys[key]->ToString();
1301class MiniscriptDescriptor final :
public DescriptorImpl
1307 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>& keys, std::span<const CScript> scripts,
1310 const auto script_ctx{
m_node->GetMsCtx()};
1311 for (
const auto& key : keys) {
1315 provider.
pubkeys.emplace(key.GetID(), key);
1318 return Vector(
m_node->ToScript(ScriptMaker(keys, script_ctx)));
1325 bool ToStringHelper(
const SigningProvider* arg, std::string&
out,
const StringType type,
1328 if (
const auto res =
m_node->ToString(StringMaker(arg, m_pubkey_args, type == StringType::PRIVATE))) {
1335 bool IsSolvable()
const override {
return true; }
1336 bool IsSingleType() const final {
return true; }
1338 std::optional<int64_t> ScriptSize()
const override {
return m_node->ScriptSize(); }
1340 std::optional<int64_t> MaxSatSize(
bool)
const override {
1342 return m_node->GetWitnessSize();
1345 std::optional<int64_t> MaxSatisfactionElems()
const override {
1346 return m_node->GetStackSize();
1349 std::unique_ptr<DescriptorImpl> Clone()
const override
1351 std::vector<std::unique_ptr<PubkeyProvider>> providers;
1352 providers.reserve(m_pubkey_args.size());
1353 for (
const auto& arg : m_pubkey_args) {
1354 providers.push_back(arg->Clone());
1356 return std::make_unique<MiniscriptDescriptor>(std::move(providers),
m_node->Clone());
1361class RawTRDescriptor final :
public DescriptorImpl
1364 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>& keys, std::span<const CScript> scripts,
FlatSigningProvider&
out)
const override
1366 assert(keys.size() == 1);
1368 if (!xpk.IsFullyValid())
return {};
1373 RawTRDescriptor(std::unique_ptr<PubkeyProvider> output_key) : DescriptorImpl(
Vector(
std::move(output_key)),
"rawtr") {}
1375 bool IsSingleType() const final {
return true; }
1377 std::optional<int64_t> ScriptSize()
const override {
return 1 + 1 + 32; }
1379 std::optional<int64_t> MaxSatisfactionWeight(
bool)
const override {
1384 std::optional<int64_t> MaxSatisfactionElems()
const override {
1389 std::unique_ptr<DescriptorImpl> Clone()
const override
1391 return std::make_unique<RawTRDescriptor>(m_pubkey_args.at(0)->Clone());
1399enum class ParseScriptContext {
1407std::optional<uint32_t> ParseKeyPathNum(std::span<const char> elem,
bool& apostrophe, std::string& error)
1409 bool hardened =
false;
1410 if (elem.size() > 0) {
1411 const char last = elem[elem.size() - 1];
1412 if (last ==
'\'' || last ==
'h') {
1413 elem = elem.first(elem.size() - 1);
1415 apostrophe = last ==
'\'';
1419 if (!
ParseUInt32(std::string(elem.begin(), elem.end()), &p)) {
1420 error =
strprintf(
"Key path value '%s' is not a valid uint32", std::string(elem.begin(), elem.end()));
1421 return std::nullopt;
1422 }
else if (p > 0x7FFFFFFFUL) {
1423 error =
strprintf(
"Key path value %u is out of range", p);
1424 return std::nullopt;
1427 return std::make_optional<uint32_t>(p | (((uint32_t)hardened) << 31));
1440[[nodiscard]]
bool ParseKeyPath(
const std::vector<std::span<const char>>&
split, std::vector<KeyPath>&
out,
bool& apostrophe, std::string& error,
bool allow_multipath)
1443 struct MultipathSubstitutes {
1444 size_t placeholder_index;
1445 std::vector<uint32_t>
values;
1447 std::optional<MultipathSubstitutes> substitutes;
1449 for (
size_t i = 1; i <
split.size(); ++i) {
1450 const std::span<const char>& elem =
split[i];
1453 if (!elem.empty() && elem.front() ==
'<' && elem.back() ==
'>') {
1454 if (!allow_multipath) {
1455 error =
strprintf(
"Key path value '%s' specifies multipath in a section where multipath is not allowed", std::string(elem.begin(), elem.end()));
1459 error =
"Multiple multipath key path specifiers found";
1464 std::vector<std::span<const char>> nums =
Split(std::span(elem.begin()+1, elem.end()-1),
";");
1465 if (nums.size() < 2) {
1466 error =
"Multipath key path specifiers must have at least two items";
1470 substitutes.emplace();
1471 std::unordered_set<uint32_t> seen_substitutes;
1472 for (
const auto& num : nums) {
1473 const auto& op_num = ParseKeyPathNum(num, apostrophe, error);
1474 if (!op_num)
return false;
1475 auto [
_, inserted] = seen_substitutes.insert(*op_num);
1477 error =
strprintf(
"Duplicated key path value %u in multipath specifier", *op_num);
1480 substitutes->values.emplace_back(*op_num);
1483 path.emplace_back();
1484 substitutes->placeholder_index = path.size() - 1;
1486 const auto& op_num = ParseKeyPathNum(elem, apostrophe, error);
1487 if (!op_num)
return false;
1488 path.emplace_back(*op_num);
1493 out.emplace_back(std::move(path));
1496 for (uint32_t substitute : substitutes->values) {
1497 KeyPath branch_path = path;
1498 branch_path[substitutes->placeholder_index] = substitute;
1499 out.emplace_back(std::move(branch_path));
1506std::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)
1508 std::vector<std::unique_ptr<PubkeyProvider>>
ret;
1509 bool permit_uncompressed = ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH;
1511 std::string str(
split[0].begin(),
split[0].end());
1512 if (str.size() == 0) {
1513 error =
"No key provided";
1517 error =
strprintf(
"Key '%s' is invalid due to whitespace", str);
1520 if (
split.size() == 1) {
1524 if (pubkey.IsValid() && !pubkey.IsValidNonHybrid()) {
1525 error =
"Hybrid public keys are not allowed";
1528 if (pubkey.IsFullyValid()) {
1529 if (permit_uncompressed || pubkey.IsCompressed()) {
1530 ret.emplace_back(std::make_unique<ConstPubkeyProvider>(key_exp_index, pubkey,
false));
1533 error =
"Uncompressed keys are not allowed";
1536 }
else if (
data.size() == 32 && ctx == ParseScriptContext::P2TR) {
1537 unsigned char fullkey[33] = {0x02};
1538 std::copy(
data.begin(),
data.end(), fullkey + 1);
1539 pubkey.Set(std::begin(fullkey), std::end(fullkey));
1540 if (pubkey.IsFullyValid()) {
1541 ret.emplace_back(std::make_unique<ConstPubkeyProvider>(key_exp_index, pubkey,
true));
1545 error =
strprintf(
"Pubkey '%s' is invalid", str);
1552 out.keys.emplace(pubkey.
GetID(), key);
1553 ret.emplace_back(std::make_unique<ConstPubkeyProvider>(key_exp_index, pubkey, ctx == ParseScriptContext::P2TR));
1556 error =
"Uncompressed keys are not allowed";
1564 error =
strprintf(
"key '%s' is not valid", str);
1567 std::vector<KeyPath> paths;
1568 DeriveType type = DeriveType::NO;
1569 if (std::ranges::equal(
split.back(), std::span{
"*"}.first(1))) {
1571 type = DeriveType::UNHARDENED;
1572 }
else if (std::ranges::equal(
split.back(), std::span{
"*'"}.first(2)) || std::ranges::equal(
split.back(), std::span{
"*h"}.first(2))) {
1573 apostrophe = std::ranges::equal(
split.back(), std::span{
"*'"}.first(2));
1575 type = DeriveType::HARDENED;
1577 if (!ParseKeyPath(
split, paths, apostrophe, error,
true))
return {};
1579 extpubkey = extkey.
Neuter();
1582 for (
auto& path : paths) {
1583 ret.emplace_back(std::make_unique<BIP32PubkeyProvider>(key_exp_index, extpubkey, std::move(path), type, apostrophe));
1589std::vector<std::unique_ptr<PubkeyProvider>> ParsePubkey(uint32_t key_exp_index,
const std::span<const char>& sp, ParseScriptContext ctx,
FlatSigningProvider&
out, std::string& error)
1591 std::vector<std::unique_ptr<PubkeyProvider>>
ret;
1592 auto origin_split =
Split(sp,
']');
1593 if (origin_split.size() > 2) {
1594 error =
"Multiple ']' characters found for a single pubkey";
1598 bool apostrophe =
false;
1599 if (origin_split.size() == 1) {
1600 return ParsePubkeyInner(key_exp_index, origin_split[0], ctx,
out, apostrophe, error);
1602 if (origin_split[0].empty() || origin_split[0][0] !=
'[') {
1603 error =
strprintf(
"Key origin start '[ character expected but not found, got '%c' instead",
1604 origin_split[0].empty() ?
']' : origin_split[0][0]);
1607 auto slash_split =
Split(origin_split[0].subspan(1),
'/');
1608 if (slash_split[0].size() != 8) {
1609 error =
strprintf(
"Fingerprint is not 4 bytes (%u characters instead of 8 characters)", slash_split[0].size());
1612 std::string fpr_hex = std::string(slash_split[0].begin(), slash_split[0].end());
1613 if (!
IsHex(fpr_hex)) {
1614 error =
strprintf(
"Fingerprint '%s' is not hex", fpr_hex);
1617 auto fpr_bytes =
ParseHex(fpr_hex);
1619 static_assert(
sizeof(info.
fingerprint) == 4,
"Fingerprint must be 4 bytes");
1620 assert(fpr_bytes.size() == 4);
1621 std::copy(fpr_bytes.begin(), fpr_bytes.end(), info.
fingerprint);
1622 std::vector<KeyPath> path;
1623 if (!ParseKeyPath(slash_split, path, apostrophe, error,
false))
return {};
1624 info.
path = path.at(0);
1625 auto providers = ParsePubkeyInner(key_exp_index, origin_split[1], ctx,
out, apostrophe, error);
1626 if (providers.empty())
return {};
1627 ret.reserve(providers.size());
1628 for (
auto& prov : providers) {
1629 ret.emplace_back(std::make_unique<OriginPubkeyProvider>(key_exp_index, info, std::move(prov), apostrophe));
1634std::unique_ptr<PubkeyProvider> InferPubkey(
const CPubKey& pubkey, ParseScriptContext ctx,
const SigningProvider& provider)
1641 if (ctx != ParseScriptContext::TOP && ctx != ParseScriptContext::P2SH && !pubkey.
IsCompressed()) {
1644 std::unique_ptr<PubkeyProvider> key_provider = std::make_unique<ConstPubkeyProvider>(0, pubkey,
false);
1647 return std::make_unique<OriginPubkeyProvider>(0, std::move(info), std::move(key_provider),
false);
1649 return key_provider;
1652std::unique_ptr<PubkeyProvider> InferXOnlyPubkey(
const XOnlyPubKey& xkey, ParseScriptContext ctx,
const SigningProvider& provider)
1655 std::unique_ptr<PubkeyProvider> key_provider = std::make_unique<ConstPubkeyProvider>(0, pubkey,
true);
1658 return std::make_unique<OriginPubkeyProvider>(0, std::move(info), std::move(key_provider),
false);
1660 return key_provider;
1668 using Key = uint32_t;
1674 mutable std::vector<std::vector<std::unique_ptr<PubkeyProvider>>> m_keys;
1676 mutable std::string m_key_parsing_error;
1684 : m_out(
out), m_in(in), m_script_ctx(ctx), m_offset(offset) {}
1686 bool KeyCompare(
const Key& a,
const Key& b)
const {
1687 return *m_keys.at(a).at(0) < *m_keys.at(b).at(0);
1691 switch (m_script_ctx) {
1698 template<
typename I> std::optional<Key>
FromString(I begin, I end)
const
1701 Key key = m_keys.
size();
1702 auto pk = ParsePubkey(m_offset + key, {&*begin, &*end},
ParseContext(), *m_out, m_key_parsing_error);
1703 if (
pk.empty())
return {};
1704 m_keys.emplace_back(std::move(
pk));
1708 std::optional<std::string>
ToString(
const Key& key)
const
1710 return m_keys.at(key).at(0)->ToString();
1713 template<
typename I> std::optional<Key> FromPKBytes(I begin, I end)
const
1716 Key key = m_keys.size();
1719 std::copy(begin, end, pubkey.
begin());
1720 if (
auto pubkey_provider = InferXOnlyPubkey(pubkey,
ParseContext(), *m_in)) {
1721 m_keys.emplace_back();
1722 m_keys.back().push_back(std::move(pubkey_provider));
1727 if (
auto pubkey_provider = InferPubkey(pubkey,
ParseContext(), *m_in)) {
1728 m_keys.emplace_back();
1729 m_keys.back().push_back(std::move(pubkey_provider));
1736 template<
typename I> std::optional<Key> FromPKHBytes(I begin, I end)
const
1738 assert(end - begin == 20);
1741 std::copy(begin, end, hash.
begin());
1745 if (
auto pubkey_provider = InferPubkey(pubkey,
ParseContext(), *m_in)) {
1746 Key key = m_keys.
size();
1747 m_keys.emplace_back();
1748 m_keys.back().push_back(std::move(pubkey_provider));
1756 return m_script_ctx;
1762std::vector<std::unique_ptr<DescriptorImpl>>
ParseScript(uint32_t& key_exp_index, std::span<const char>& sp, ParseScriptContext ctx,
FlatSigningProvider&
out, std::string& error)
1765 Assume(ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH || ctx == ParseScriptContext::P2TR);
1766 std::vector<std::unique_ptr<DescriptorImpl>>
ret;
1767 auto expr =
Expr(sp);
1768 if (
Func(
"pk", expr)) {
1769 auto pubkeys = ParsePubkey(key_exp_index, expr, ctx,
out, error);
1770 if (pubkeys.empty()) {
1775 for (
auto& pubkey : pubkeys) {
1776 ret.emplace_back(std::make_unique<PKDescriptor>(std::move(pubkey), ctx == ParseScriptContext::P2TR));
1780 if ((ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH) &&
Func(
"pkh", expr)) {
1781 auto pubkeys = ParsePubkey(key_exp_index, expr, ctx,
out, error);
1782 if (pubkeys.empty()) {
1787 for (
auto& pubkey : pubkeys) {
1788 ret.emplace_back(std::make_unique<PKHDescriptor>(std::move(pubkey)));
1792 if (ctx == ParseScriptContext::TOP &&
Func(
"combo", expr)) {
1793 auto pubkeys = ParsePubkey(key_exp_index, expr, ctx,
out, error);
1794 if (pubkeys.empty()) {
1795 error =
strprintf(
"combo(): %s", error);
1799 for (
auto& pubkey : pubkeys) {
1800 ret.emplace_back(std::make_unique<ComboDescriptor>(std::move(pubkey)));
1803 }
else if (
Func(
"combo", expr)) {
1804 error =
"Can only have combo() at top level";
1807 const bool multi =
Func(
"multi", expr);
1808 const bool sortedmulti = !multi &&
Func(
"sortedmulti", expr);
1809 const bool multi_a = !(multi || sortedmulti) &&
Func(
"multi_a", expr);
1810 const bool sortedmulti_a = !(multi || sortedmulti || multi_a) &&
Func(
"sortedmulti_a", expr);
1811 if (((ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH) && (multi || sortedmulti)) ||
1812 (ctx == ParseScriptContext::P2TR && (multi_a || sortedmulti_a))) {
1813 auto threshold =
Expr(expr);
1815 std::vector<std::vector<std::unique_ptr<PubkeyProvider>>> providers;
1816 if (!
ParseUInt32(std::string(threshold.begin(), threshold.end()), &thres)) {
1817 error =
strprintf(
"Multi threshold '%s' is not valid", std::string(threshold.begin(), threshold.end()));
1820 size_t script_size = 0;
1821 size_t max_providers_len = 0;
1822 while (expr.size()) {
1823 if (!
Const(
",", expr)) {
1824 error =
strprintf(
"Multi: expected ',', got '%c'", expr[0]);
1827 auto arg =
Expr(expr);
1828 auto pks = ParsePubkey(key_exp_index, arg, ctx,
out, error);
1833 script_size += pks.at(0)->GetSize() + 1;
1834 max_providers_len = std::max(max_providers_len, pks.size());
1835 providers.emplace_back(std::move(pks));
1844 }
else if (thres < 1) {
1845 error =
strprintf(
"Multisig threshold cannot be %d, must be at least 1", thres);
1847 }
else if (thres > providers.size()) {
1848 error =
strprintf(
"Multisig threshold cannot be larger than the number of keys; threshold is %d but only %u keys specified", thres, providers.size());
1851 if (ctx == ParseScriptContext::TOP) {
1852 if (providers.size() > 3) {
1853 error =
strprintf(
"Cannot have %u pubkeys in bare multisig; only at most 3 pubkeys", providers.size());
1857 if (ctx == ParseScriptContext::P2SH) {
1867 for (
auto& vec : providers) {
1868 if (vec.size() == 1) {
1869 for (
size_t i = 1; i < max_providers_len; ++i) {
1870 vec.emplace_back(vec.at(0)->Clone());
1872 }
else if (vec.size() != max_providers_len) {
1873 error =
strprintf(
"multi(): Multipath derivation paths have mismatched lengths");
1879 for (
size_t i = 0; i < max_providers_len; ++i) {
1881 std::vector<std::unique_ptr<PubkeyProvider>> pubs;
1882 pubs.reserve(providers.size());
1883 for (
auto& pub : providers) {
1884 pubs.emplace_back(std::move(pub.at(i)));
1886 if (multi || sortedmulti) {
1887 ret.emplace_back(std::make_unique<MultisigDescriptor>(thres, std::move(pubs), sortedmulti));
1889 ret.emplace_back(std::make_unique<MultiADescriptor>(thres, std::move(pubs), sortedmulti_a));
1893 }
else if (multi || sortedmulti) {
1894 error =
"Can only have multi/sortedmulti at top level, in sh(), or in wsh()";
1896 }
else if (multi_a || sortedmulti_a) {
1897 error =
"Can only have multi_a/sortedmulti_a inside tr()";
1900 if ((ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH) &&
Func(
"wpkh", expr)) {
1901 auto pubkeys = ParsePubkey(key_exp_index, expr, ParseScriptContext::P2WPKH,
out, error);
1902 if (pubkeys.empty()) {
1907 for (
auto& pubkey : pubkeys) {
1908 ret.emplace_back(std::make_unique<WPKHDescriptor>(std::move(pubkey)));
1911 }
else if (
Func(
"wpkh", expr)) {
1912 error =
"Can only have wpkh() at top level or inside sh()";
1915 if (ctx == ParseScriptContext::TOP &&
Func(
"sh", expr)) {
1916 auto descs =
ParseScript(key_exp_index, expr, ParseScriptContext::P2SH,
out, error);
1917 if (descs.empty() || expr.size())
return {};
1918 std::vector<std::unique_ptr<DescriptorImpl>>
ret;
1919 ret.reserve(descs.size());
1920 for (
auto& desc : descs) {
1921 ret.push_back(std::make_unique<SHDescriptor>(std::move(desc)));
1924 }
else if (
Func(
"sh", expr)) {
1925 error =
"Can only have sh() at top level";
1928 if ((ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH) &&
Func(
"wsh", expr)) {
1929 auto descs =
ParseScript(key_exp_index, expr, ParseScriptContext::P2WSH,
out, error);
1930 if (descs.empty() || expr.size())
return {};
1931 for (
auto& desc : descs) {
1932 ret.emplace_back(std::make_unique<WSHDescriptor>(std::move(desc)));
1935 }
else if (
Func(
"wsh", expr)) {
1936 error =
"Can only have wsh() at top level or inside sh()";
1939 if (ctx == ParseScriptContext::TOP &&
Func(
"addr", expr)) {
1942 error =
"Address is not valid";
1945 ret.emplace_back(std::make_unique<AddressDescriptor>(std::move(dest)));
1947 }
else if (
Func(
"addr", expr)) {
1948 error =
"Can only have addr() at top level";
1951 if (ctx == ParseScriptContext::TOP &&
Func(
"tr", expr)) {
1952 auto arg =
Expr(expr);
1953 auto internal_keys = ParsePubkey(key_exp_index, arg, ParseScriptContext::P2TR,
out, error);
1954 if (internal_keys.empty()) {
1958 size_t max_providers_len = internal_keys.size();
1960 std::vector<std::vector<std::unique_ptr<DescriptorImpl>>> subscripts;
1961 std::vector<int> depths;
1963 if (!
Const(
",", expr)) {
1964 error =
strprintf(
"tr: expected ',', got '%c'", expr[0]);
1970 std::vector<bool> branches;
1975 while (
Const(
"{", expr)) {
1976 branches.push_back(
false);
1983 auto sarg =
Expr(expr);
1984 subscripts.emplace_back(
ParseScript(key_exp_index, sarg, ParseScriptContext::P2TR,
out, error));
1985 if (subscripts.back().empty())
return {};
1986 max_providers_len = std::max(max_providers_len, subscripts.back().size());
1987 depths.push_back(branches.size());
1989 while (branches.size() && branches.back()) {
1990 if (!
Const(
"}", expr)) {
1991 error =
strprintf(
"tr(): expected '}' after script expression");
1994 branches.pop_back();
1997 if (branches.size() && !branches.back()) {
1998 if (!
Const(
",", expr)) {
1999 error =
strprintf(
"tr(): expected ',' after script expression");
2002 branches.back() =
true;
2004 }
while (branches.size());
2007 error =
strprintf(
"tr(): expected ')' after script expression");
2015 for (
auto& vec : subscripts) {
2016 if (vec.size() == 1) {
2017 for (
size_t i = 1; i < max_providers_len; ++i) {
2018 vec.emplace_back(vec.at(0)->Clone());
2020 }
else if (vec.size() != max_providers_len) {
2021 error =
strprintf(
"tr(): Multipath subscripts have mismatched lengths");
2026 if (internal_keys.size() > 1 && internal_keys.size() != max_providers_len) {
2027 error =
strprintf(
"tr(): Multipath internal key mismatches multipath subscripts lengths");
2031 while (internal_keys.size() < max_providers_len) {
2032 internal_keys.emplace_back(internal_keys.at(0)->Clone());
2036 for (
size_t i = 0; i < max_providers_len; ++i) {
2038 std::vector<std::unique_ptr<DescriptorImpl>> this_subs;
2039 this_subs.reserve(subscripts.size());
2040 for (
auto& subs : subscripts) {
2041 this_subs.emplace_back(std::move(subs.at(i)));
2043 ret.emplace_back(std::make_unique<TRDescriptor>(std::move(internal_keys.at(i)), std::move(this_subs), depths));
2048 }
else if (
Func(
"tr", expr)) {
2049 error =
"Can only have tr at top level";
2052 if (ctx == ParseScriptContext::TOP &&
Func(
"rawtr", expr)) {
2053 auto arg =
Expr(expr);
2055 error =
strprintf(
"rawtr(): only one key expected.");
2058 auto output_keys = ParsePubkey(key_exp_index, arg, ParseScriptContext::P2TR,
out, error);
2059 if (output_keys.empty()) {
2060 error =
strprintf(
"rawtr(): %s", error);
2064 for (
auto& pubkey : output_keys) {
2065 ret.emplace_back(std::make_unique<RawTRDescriptor>(std::move(pubkey)));
2068 }
else if (
Func(
"rawtr", expr)) {
2069 error =
"Can only have rawtr at top level";
2072 if (ctx == ParseScriptContext::TOP &&
Func(
"raw", expr)) {
2073 std::string str(expr.begin(), expr.end());
2075 error =
"Raw script is not hex";
2079 ret.emplace_back(std::make_unique<RawDescriptor>(
CScript(bytes.begin(), bytes.end())));
2081 }
else if (
Func(
"raw", expr)) {
2082 error =
"Can only have raw() at top level";
2088 KeyParser parser(&
out,
nullptr, script_ctx, key_exp_index);
2090 if (parser.m_key_parsing_error !=
"") {
2091 error = std::move(parser.m_key_parsing_error);
2095 if (ctx != ParseScriptContext::P2WSH && ctx != ParseScriptContext::P2TR) {
2096 error =
"Miniscript expressions can only be used in wsh or tr.";
2099 if (!
node->IsSane() ||
node->IsNotSatisfiable()) {
2101 auto insane_node =
node.get();
2102 if (
const auto sub =
node->FindInsaneSub()) insane_node = sub;
2103 if (
const auto str = insane_node->ToString(parser)) error = *str;
2104 if (!insane_node->IsValid()) {
2105 error +=
" is invalid";
2106 }
else if (!
node->IsSane()) {
2107 error +=
" is not sane";
2108 if (!insane_node->IsNonMalleable()) {
2109 error +=
": malleable witnesses exist";
2110 }
else if (insane_node ==
node.get() && !insane_node->NeedsSignature()) {
2111 error +=
": witnesses without signature exist";
2112 }
else if (!insane_node->CheckTimeLocksMix()) {
2113 error +=
": contains mixes of timelocks expressed in blocks and seconds";
2114 }
else if (!insane_node->CheckDuplicateKey()) {
2115 error +=
": contains duplicate public keys";
2116 }
else if (!insane_node->ValidSatisfactions()) {
2117 error +=
": needs witnesses that may exceed resource limits";
2120 error +=
" is not satisfiable";
2127 key_exp_index += parser.m_keys.size();
2130 size_t num_multipath = std::max_element(parser.m_keys.begin(), parser.m_keys.end(),
2131 [](
const std::vector<std::unique_ptr<PubkeyProvider>>& a,
const std::vector<std::unique_ptr<PubkeyProvider>>& b) {
2132 return a.size() < b.size();
2135 for (
auto& vec : parser.m_keys) {
2136 if (vec.size() == 1) {
2137 for (
size_t i = 1; i < num_multipath; ++i) {
2138 vec.emplace_back(vec.at(0)->Clone());
2140 }
else if (vec.size() != num_multipath) {
2141 error =
strprintf(
"Miniscript: Multipath derivation paths have mismatched lengths");
2147 for (
size_t i = 0; i < num_multipath; ++i) {
2149 std::vector<std::unique_ptr<PubkeyProvider>> pubs;
2150 pubs.reserve(parser.m_keys.size());
2151 for (
auto& pub : parser.m_keys) {
2152 pubs.emplace_back(std::move(pub.at(i)));
2154 ret.emplace_back(std::make_unique<MiniscriptDescriptor>(std::move(pubs),
node->Clone()));
2159 if (ctx == ParseScriptContext::P2SH) {
2160 error =
"A function is needed within P2SH";
2162 }
else if (ctx == ParseScriptContext::P2WSH) {
2163 error =
"A function is needed within P2WSH";
2166 error =
strprintf(
"'%s' is not a valid descriptor function", std::string(expr.begin(), expr.end()));
2173 if (!match)
return {};
2174 std::vector<std::unique_ptr<PubkeyProvider>> keys;
2175 keys.reserve(match->second.size());
2176 for (
const auto keyspan : match->second) {
2177 if (keyspan.size() != 32)
return {};
2178 auto key = InferXOnlyPubkey(
XOnlyPubKey{keyspan}, ctx, provider);
2179 if (!key)
return {};
2180 keys.push_back(std::move(key));
2182 return std::make_unique<MultiADescriptor>(match->first, std::move(keys));
2190 return std::make_unique<PKDescriptor>(InferXOnlyPubkey(key, ctx, provider),
true);
2193 if (ctx == ParseScriptContext::P2TR) {
2194 auto ret = InferMultiA(
script, ctx, provider);
2198 std::vector<std::vector<unsigned char>>
data;
2201 if (txntype ==
TxoutType::PUBKEY && (ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH)) {
2203 if (
auto pubkey_provider = InferPubkey(pubkey, ctx, provider)) {
2204 return std::make_unique<PKDescriptor>(std::move(pubkey_provider));
2207 if (txntype ==
TxoutType::PUBKEYHASH && (ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH)) {
2211 if (provider.
GetPubKey(keyid, pubkey)) {
2212 if (
auto pubkey_provider = InferPubkey(pubkey, ctx, provider)) {
2213 return std::make_unique<PKHDescriptor>(std::move(pubkey_provider));
2221 if (provider.
GetPubKey(keyid, pubkey)) {
2222 if (
auto pubkey_provider = InferPubkey(pubkey, ParseScriptContext::P2WPKH, provider)) {
2223 return std::make_unique<WPKHDescriptor>(std::move(pubkey_provider));
2227 if (txntype ==
TxoutType::MULTISIG && (ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH)) {
2229 std::vector<std::unique_ptr<PubkeyProvider>> providers;
2230 for (
size_t i = 1; i + 1 <
data.size(); ++i) {
2232 if (
auto pubkey_provider = InferPubkey(pubkey, ctx, provider)) {
2233 providers.push_back(std::move(pubkey_provider));
2239 if (ok)
return std::make_unique<MultisigDescriptor>((
int)
data[0][0], std::move(providers));
2245 if (provider.
GetCScript(scriptid, subscript)) {
2246 auto sub = InferScript(subscript, ParseScriptContext::P2SH, provider);
2247 if (sub)
return std::make_unique<SHDescriptor>(std::move(sub));
2253 if (provider.
GetCScript(scriptid, subscript)) {
2254 auto sub = InferScript(subscript, ParseScriptContext::P2WSH, provider);
2255 if (sub)
return std::make_unique<WSHDescriptor>(std::move(sub));
2270 std::vector<std::unique_ptr<DescriptorImpl>> subscripts;
2271 std::vector<int> depths;
2272 for (
const auto& [depth,
script, leaf_ver] : *tree) {
2273 std::unique_ptr<DescriptorImpl> subdesc;
2275 subdesc = InferScript(
CScript(
script.begin(),
script.end()), ParseScriptContext::P2TR, provider);
2281 subscripts.push_back(std::move(subdesc));
2282 depths.push_back(depth);
2286 auto key = InferXOnlyPubkey(tap.
internal_key, ParseScriptContext::P2TR, provider);
2287 return std::make_unique<TRDescriptor>(std::move(key), std::move(subscripts), std::move(depths));
2293 auto key = InferXOnlyPubkey(pubkey, ParseScriptContext::P2TR, provider);
2295 return std::make_unique<RawTRDescriptor>(std::move(key));
2300 if (ctx == ParseScriptContext::P2WSH || ctx == ParseScriptContext::P2TR) {
2302 KeyParser parser(
nullptr, &provider, script_ctx);
2305 std::vector<std::unique_ptr<PubkeyProvider>> keys;
2306 keys.reserve(parser.m_keys.size());
2307 for (
auto& key : parser.m_keys) {
2308 keys.emplace_back(std::move(key.at(0)));
2310 return std::make_unique<MiniscriptDescriptor>(std::move(keys), std::move(
node));
2316 if (ctx != ParseScriptContext::TOP)
return nullptr;
2321 return std::make_unique<AddressDescriptor>(std::move(dest));
2325 return std::make_unique<RawDescriptor>(
script);
2332bool CheckChecksum(std::span<const char>& sp,
bool require_checksum, std::string& error, std::string* out_checksum =
nullptr)
2334 auto check_split =
Split(sp,
'#');
2335 if (check_split.size() > 2) {
2336 error =
"Multiple '#' symbols";
2339 if (check_split.size() == 1 && require_checksum){
2340 error =
"Missing checksum";
2343 if (check_split.size() == 2) {
2344 if (check_split[1].size() != 8) {
2345 error =
strprintf(
"Expected 8 character checksum, not %u characters", check_split[1].size());
2349 auto checksum = DescriptorChecksum(check_split[0]);
2350 if (checksum.empty()) {
2351 error =
"Invalid characters in payload";
2354 if (check_split.size() == 2) {
2355 if (!std::equal(checksum.begin(), checksum.end(), check_split[1].begin())) {
2356 error =
strprintf(
"Provided checksum '%s' does not match computed checksum '%s'", std::string(check_split[1].begin(), check_split[1].end()), checksum);
2360 if (out_checksum) *out_checksum = std::move(checksum);
2361 sp = check_split[0];
2367 std::span<const char> sp{descriptor};
2369 uint32_t key_exp_index = 0;
2371 if (sp.size() == 0 && !
ret.empty()) {
2372 std::vector<std::unique_ptr<Descriptor>> descs;
2373 descs.reserve(
ret.size());
2374 for (
auto& r :
ret) {
2375 descs.emplace_back(std::unique_ptr<Descriptor>(std::move(r)));
2386 std::span<const char> sp{descriptor};
2393 return InferScript(
script, ParseScriptContext::TOP, provider);
2398 std::string desc_str = desc.
ToString(
true);
2412 xpubs[der_index] = xpub;
2432 const auto& der_it = key_exp_it->second.find(der_index);
2433 if (der_it == key_exp_it->second.end())
return false;
2434 xpub = der_it->second;
2452 if (xpub != parent_xpub_pair.second) {
2453 throw std::runtime_error(std::string(__func__) +
": New cached parent xpub does not match already cached parent xpub");
2461 for (
const auto& derived_xpub_pair : derived_xpub_map_pair.second) {
2464 if (xpub != derived_xpub_pair.second) {
2465 throw std::runtime_error(std::string(__func__) +
": New cached derived xpub does not match already cached derived xpub");
2469 CacheDerivedExtPubKey(derived_xpub_map_pair.first, derived_xpub_pair.first, derived_xpub_pair.second);
2470 diff.
CacheDerivedExtPubKey(derived_xpub_map_pair.first, derived_xpub_pair.first, derived_xpub_pair.second);
2476 if (xpub != lh_xpub_pair.second) {
2477 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 Assume(val)
Assume is the identity function.
An encapsulated private key.
unsigned int size() const
Simple read-only vector-like interface.
bool IsValid() const
Check whether this private key is valid.
bool IsCompressed() const
Check whether the public key corresponding to this private key is (to be) compressed.
CPubKey GetPubKey() const
Compute the public key from a private key.
A reference to a CKey: the Hash160 of its serialized public key.
An encapsulated public key.
bool IsCompressed() const
Check whether this is a compressed public key.
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
bool IsValidNonHybrid() const noexcept
Check if a public key is a syntactically valid compressed or uncompressed key.
A hasher class for SHA-256.
void Finalize(unsigned char hash[OUTPUT_SIZE])
CSHA256 & Write(const unsigned char *data, size_t len)
Serialized script, used inside transaction inputs and outputs.
A reference to a CScript: the Hash160 of its serialization.
Cache for single descriptor's derived extended pubkeys.
bool GetCachedParentExtPubKey(uint32_t key_exp_pos, CExtPubKey &xpub) const
Retrieve a cached parent xpub.
std::unordered_map< uint32_t, ExtPubKeyMap > GetCachedDerivedExtPubKeys() const
Retrieve all cached derived xpubs.
ExtPubKeyMap m_last_hardened_xpubs
Map key expression index -> last hardened xpub.
void CacheDerivedExtPubKey(uint32_t key_exp_pos, uint32_t der_index, const CExtPubKey &xpub)
Cache an xpub derived at an index.
DescriptorCache MergeAndDiff(const DescriptorCache &other)
Combine another DescriptorCache into this one.
ExtPubKeyMap GetCachedParentExtPubKeys() const
Retrieve all cached parent xpubs.
ExtPubKeyMap GetCachedLastHardenedExtPubKeys() const
Retrieve all cached last hardened xpubs.
void CacheParentExtPubKey(uint32_t key_exp_pos, const CExtPubKey &xpub)
Cache a parent xpub.
void CacheLastHardenedExtPubKey(uint32_t key_exp_pos, const CExtPubKey &xpub)
Cache a last hardened xpub.
bool GetCachedDerivedExtPubKey(uint32_t key_exp_pos, uint32_t der_index, CExtPubKey &xpub) const
Retrieve a cached xpub derived at an index.
std::unordered_map< uint32_t, ExtPubKeyMap > m_derived_xpubs
Map key expression index -> map of (key derivation index -> xpub)
bool GetCachedLastHardenedExtPubKey(uint32_t key_exp_pos, CExtPubKey &xpub) const
Retrieve a cached last hardened xpub.
ExtPubKeyMap m_parent_xpubs
Map key expression index -> parent xpub.
An interface to be implemented by keystores that support signing.
virtual bool GetCScript(const CScriptID &scriptid, CScript &script) const
virtual bool GetTaprootSpendData(const XOnlyPubKey &output_key, TaprootSpendData &spenddata) const
bool GetKeyByXOnly(const XOnlyPubKey &pubkey, CKey &key) const
virtual bool GetPubKey(const CKeyID &address, CPubKey &pubkey) const
bool GetKeyOriginByXOnly(const XOnlyPubKey &pubkey, KeyOriginInfo &info) const
virtual bool GetKey(const CKeyID &address, CKey &key) const
virtual bool GetKeyOrigin(const CKeyID &keyid, KeyOriginInfo &info) const
Utility class to construct Taproot outputs from internal key and script tree.
WitnessV1Taproot GetOutput()
Compute scriptPubKey (after Finalize()).
bool IsComplete() const
Return whether there were either no leaves, or the leaves form a Huffman tree.
TaprootBuilder & Add(int depth, std::span< const unsigned char > script, int leaf_version, bool track=true)
Add a new script at a certain depth in the tree.
static bool ValidDepths(const std::vector< int > &depths)
Check if a list of depths is legal (will lead to IsComplete()).
TaprootBuilder & Finalize(const XOnlyPubKey &internal_key)
Finalize the construction.
const unsigned char * begin() const
static constexpr size_t size()
CPubKey GetEvenCorrespondingCPubKey() const
bool IsFullyValid() const
Determine if this pubkey is fully valid.
constexpr unsigned char * begin()
static const int WITNESS_SCALE_FACTOR
CScript ParseScript(const std::string &s)
uint160 Hash160(const T1 &in1)
Compute the 160-bit hash an object.
uint160 RIPEMD160(std::span< const unsigned char > data)
Compute the 160-bit RIPEMD-160 hash of an array.
std::string HexStr(const std::span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
static constexpr uint8_t TAPROOT_LEAF_TAPSCRIPT
static constexpr size_t TAPROOT_CONTROL_MAX_NODE_COUNT
std::string EncodeExtKey(const CExtKey &key)
CExtPubKey DecodeExtPubKey(const std::string &str)
CTxDestination DecodeDestination(const std::string &str, std::string &error_msg, std::vector< int > *error_locations)
std::string EncodeSecret(const CKey &key)
std::string EncodeDestination(const CTxDestination &dest)
CKey DecodeSecret(const std::string &str)
std::string EncodeExtPubKey(const CExtPubKey &key)
CExtKey DecodeExtKey(const std::string &str)
NodeRef< typename Ctx::Key > FromString(const std::string &str, const Ctx &ctx)
constexpr bool IsTapscript(MiniscriptContext ms_ctx)
Whether the context Tapscript, ensuring the only other possibility is P2WSH.
NodeRef< typename Ctx::Key > FromScript(const CScript &script, const Ctx &ctx)
std::unique_ptr< const Node< Key > > NodeRef
std::span< const char > Expr(std::span< const char > &sp)
Extract the expression that sp begins with.
bool Const(const std::string &str, std::span< const char > &sp)
Parse a constant.
bool Func(const std::string &str, std::span< const char > &sp)
Parse a function call.
static std::vector< std::string > split(const std::string &str, const std::string &delims=" \t")
std::vector< T > Split(const std::span< const char > &sp, std::string_view separators)
Split a string on any char found in separators, returning a vector.
std::string ToString(const T &t)
Locale-independent version of std::to_string.
static OutputType GetOutputType(TxoutType type, bool is_from_p2sh)
static bool IsSegwit(const Descriptor &desc)
Whether the descriptor represents, directly or not, a witness program.
bool operator<(const CNetAddr &a, const CNetAddr &b)
std::optional< OutputType > OutputTypeFromDestination(const CTxDestination &dest)
Get the OutputType for a CTxDestination.
std::unique_ptr< Descriptor > InferDescriptor(const CScript &script, const SigningProvider &provider)
Find a descriptor for the specified script, using information from provider where possible.
uint256 DescriptorID(const Descriptor &desc)
Unique identifier that may not change over time, unless explicitly marked as not backwards compatible...
bool CheckChecksum(std::span< const char > &sp, bool require_checksum, std::string &error, std::string *out_checksum=nullptr)
Check a descriptor checksum, and update desc to be the checksum-less part.
std::vector< std::unique_ptr< Descriptor > > Parse(const std::string &descriptor, FlatSigningProvider &out, std::string &error, bool require_checksum)
Parse a descriptor string.
std::string GetDescriptorChecksum(const std::string &descriptor)
Get the checksum for a descriptor.
std::unordered_map< uint32_t, CExtPubKey > ExtPubKeyMap
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE
static constexpr unsigned int MAX_PUBKEYS_PER_MULTI_A
The limit of keys in OP_CHECKSIGADD-based scripts.
CScript BuildScript(Ts &&... inputs)
Build a script by concatenating other scripts, or any argument accepted by CScript::operator<<.
static const int MAX_PUBKEYS_PER_MULTISIG
std::vector< unsigned char > ToByteVector(const T &in)
static const int64_t values[]
A selection of numbers that do not trigger int64_t overflow when added/subtracted.
constexpr unsigned int GetSizeOfCompactSize(uint64_t nSize)
Compact Size size < 253 – 1 byte size <= USHRT_MAX – 3 bytes (253 + 2 bytes) size <= UINT_MAX – 5 byt...
static bool GetPubKey(const SigningProvider &provider, const SignatureData &sigdata, const CKeyID &address, CPubKey &pubkey)
std::optional< std::vector< std::tuple< int, std::vector< unsigned char >, int > > > InferTaprootTree(const TaprootSpendData &spenddata, const XOnlyPubKey &output)
Given a TaprootSpendData and the output key, reconstruct its script tree.
const SigningProvider & DUMMY_SIGNING_PROVIDER
void PolyMod(const std::vector< typename F::Elem > &mod, std::vector< typename F::Elem > &val, const F &field)
Compute the remainder of a polynomial division of val by mod, putting the result in mod.
TxoutType Solver(const CScript &scriptPubKey, std::vector< std::vector< unsigned char > > &vSolutionsRet)
Parse a scriptPubKey and identify script type for standard scripts.
CScript GetScriptForMultisig(int nRequired, const std::vector< CPubKey > &keys)
Generate a multisig script.
std::optional< std::pair< int, std::vector< std::span< const unsigned char > > > > MatchMultiA(const CScript &script)
CScript GetScriptForRawPubKey(const CPubKey &pubKey)
Generate a P2PK script for the given pubkey.
std::vector< Byte > ParseHex(std::string_view hex_str)
Like TryParseHex, but returns an empty vector on invalid input.
constexpr bool IsSpace(char c) noexcept
Tests if the given character is a whitespace character.
CExtPubKey Neuter() const
bool Derive(CExtKey &out, unsigned int nChild) const
bool Derive(CExtPubKey &out, unsigned int nChild) const
Interface for parsed descriptor objects.
virtual std::optional< int64_t > MaxSatisfactionElems() const =0
Get the maximum size number of stack elements for satisfying this descriptor.
virtual void GetPubKeys(std::set< CPubKey > &pubkeys, std::set< CExtPubKey > &ext_pubs) const =0
Return all (extended) public keys for this descriptor, including any from subdescriptors.
virtual bool ToNormalizedString(const SigningProvider &provider, std::string &out, const DescriptorCache *cache=nullptr) const =0
Convert the descriptor to a normalized string.
virtual std::optional< int64_t > MaxSatisfactionWeight(bool use_max_sig) const =0
Get the maximum size of a satisfaction for this descriptor, in weight units.
virtual std::string ToString(bool compat_format=false) const =0
Convert the descriptor back to a string, undoing parsing.
virtual std::optional< OutputType > GetOutputType() const =0
virtual bool Expand(int pos, const SigningProvider &provider, std::vector< CScript > &output_scripts, FlatSigningProvider &out, DescriptorCache *write_cache=nullptr) const =0
Expand a descriptor at a specified position.
virtual bool IsRange() const =0
Whether the expansion of this descriptor depends on the position.
virtual std::optional< int64_t > ScriptSize() const =0
Get the size of the scriptPubKey for this descriptor.
virtual bool IsSolvable() const =0
Whether this descriptor has all information about signing ignoring lack of private keys.
virtual void ExpandPrivate(int pos, const SigningProvider &provider, FlatSigningProvider &out) const =0
Expand the private key for a descriptor at a specified position, if possible.
virtual bool ToPrivateString(const SigningProvider &provider, std::string &out) const =0
Convert the descriptor to a private string.
virtual bool ExpandFromCache(int pos, const DescriptorCache &read_cache, std::vector< CScript > &output_scripts, FlatSigningProvider &out) const =0
Expand a descriptor at a specified position using cached expansion data.
std::map< CKeyID, CPubKey > pubkeys
unsigned char fingerprint[4]
First 32 bits of the Hash160 of the public key at the root of the path.
std::vector< uint32_t > path
XOnlyPubKey internal_key
The BIP341 internal key.
consteval auto _(util::TranslatedLiteral str)
bool IsHex(std::string_view str)
bool ParseUInt32(std::string_view str, uint32_t *out)
Convert decimal string to unsigned 32-bit integer with strict parse error feedback.
std::vector< std::common_type_t< Args... > > Vector(Args &&... args)
Construct a vector with the specified elements.