92 uint64_t
PolyMod(uint64_t c,
int val)
95 c = ((c & 0x7ffffffff) << 5) ^ val;
96 if (c0 & 1) c ^= 0xf5dee51989;
97 if (c0 & 2) c ^= 0xa9fdca3312;
98 if (c0 & 4) c ^= 0x1bab10e32d;
99 if (c0 & 8) c ^= 0x3706b1677a;
100 if (c0 & 16) c ^= 0x644d626ffd;
119 static const std::string INPUT_CHARSET =
120 "0123456789()[],'/*abcdefgh@:$%{}" 121 "IJKLMNOPQRSTUVWXYZ&+-.;<=>?!^_|~" 122 "ijklmnopqrstuvwxyzABCDEFGH`#\"\\ ";
125 static const std::string CHECKSUM_CHARSET =
"qpzry9x8gf2tvdw0s3jn54khce6mua7l";
130 for (
auto ch : span) {
131 auto pos = INPUT_CHARSET.find(ch);
132 if (pos == std::string::npos)
return "";
134 cls = cls * 3 + (pos >> 5);
135 if (++clscount == 3) {
142 if (clscount > 0) c =
PolyMod(c, cls);
143 for (
int j = 0; j < 8; ++j) c =
PolyMod(c, 0);
146 std::string
ret(8,
' ');
147 for (
int j = 0; j < 8; ++j) ret[j] = CHECKSUM_CHARSET[(c >> (5 * (7 - j))) & 31];
151 std::string AddChecksum(
const std::string& str) {
return str +
"#" + DescriptorChecksum(str); }
157 typedef std::vector<uint32_t> KeyPath;
160 struct PubkeyProvider
165 uint32_t m_expr_index;
168 explicit PubkeyProvider(uint32_t exp_index) : m_expr_index(exp_index) {}
170 virtual ~PubkeyProvider() =
default;
175 bool operator<(PubkeyProvider& other)
const {
181 other.GetPubKey(0, dummy, b, dummy_info);
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 class OriginPubkeyProvider final :
public PubkeyProvider
227 std::unique_ptr<PubkeyProvider> m_provider;
230 std::string OriginString(StringType type,
bool normalized=
false)
const 233 bool use_apostrophe = (!normalized && m_apostrophe) || type == StringType::COMPAT;
238 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) {}
241 if (!m_provider->GetPubKey(pos, arg, key, info, read_cache, write_cache))
return false;
242 std::copy(std::begin(m_origin.fingerprint), std::end(m_origin.fingerprint), info.
fingerprint);
243 info.
path.insert(info.
path.begin(), m_origin.path.begin(), m_origin.path.end());
246 bool IsRange()
const override {
return m_provider->IsRange(); }
247 size_t GetSize()
const override {
return m_provider->GetSize(); }
248 std::string
ToString(StringType type)
const override {
return "[" + OriginString(type) +
"]" + m_provider->ToString(type); }
252 if (!m_provider->ToPrivateString(arg, sub))
return false;
253 ret =
"[" + OriginString(StringType::PUBLIC) +
"]" + std::move(sub);
259 if (!m_provider->ToNormalizedString(arg, sub, cache))
return false;
265 ret =
"[" + OriginString(StringType::PUBLIC,
true) + std::move(sub);
267 ret =
"[" + OriginString(StringType::PUBLIC,
true) +
"]" + std::move(sub);
273 return m_provider->GetPrivKey(pos, arg, key);
275 std::optional<CPubKey> GetRootPubKey()
const override 277 return m_provider->GetRootPubKey();
279 std::optional<CExtPubKey> GetRootExtPubKey()
const override 281 return m_provider->GetRootExtPubKey();
286 class ConstPubkeyProvider final :
public PubkeyProvider
292 ConstPubkeyProvider(uint32_t exp_index,
const CPubKey& pubkey,
bool xonly) : PubkeyProvider(exp_index), m_pubkey(pubkey), m_xonly(xonly) {}
297 CKeyID keyid = m_pubkey.GetID();
301 bool IsRange()
const override {
return false; }
302 size_t GetSize()
const override {
return m_pubkey.size(); }
303 std::string
ToString(StringType type)
const override {
return m_xonly ?
HexStr(m_pubkey).substr(2) :
HexStr(m_pubkey); }
308 for (
const auto& keyid :
XOnlyPubKey(m_pubkey).GetKeyIDs()) {
313 arg.
GetKey(m_pubkey.GetID(), key);
315 if (!key.
IsValid())
return false;
326 return arg.
GetKey(m_pubkey.GetID(), key);
328 std::optional<CPubKey> GetRootPubKey()
const override 332 std::optional<CExtPubKey> GetRootExtPubKey()
const override 345 class BIP32PubkeyProvider final :
public PubkeyProvider
357 if (!arg.
GetKey(m_root_extkey.pubkey.GetID(), key))
return false;
358 ret.nDepth = m_root_extkey.nDepth;
359 std::copy(m_root_extkey.vchFingerprint, m_root_extkey.vchFingerprint +
sizeof(
ret.vchFingerprint),
ret.vchFingerprint);
360 ret.nChild = m_root_extkey.nChild;
361 ret.chaincode = m_root_extkey.chaincode;
369 if (!GetExtKey(arg, xprv))
return false;
370 for (
auto entry : m_path) {
371 if (!xprv.
Derive(xprv, entry))
return false;
373 last_hardened = xprv;
379 bool IsHardened()
const 381 if (m_derive == DeriveType::HARDENED)
return true;
382 for (
auto entry : m_path) {
383 if (entry >> 31)
return true;
389 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) {}
390 bool IsRange()
const override {
return m_derive != DeriveType::NO; }
391 size_t GetSize()
const override {
return 33; }
396 CKeyID keyid = m_root_extkey.pubkey.GetID();
398 parent_info.
path = m_path;
402 if (m_derive == DeriveType::UNHARDENED) final_info_out_tmp.
path.push_back((uint32_t)pos);
403 if (m_derive == DeriveType::HARDENED) final_info_out_tmp.
path.push_back(((uint32_t)pos) | 0x80000000L);
411 if (!read_cache->GetCachedDerivedExtPubKey(m_expr_index, pos, final_extkey)) {
412 if (m_derive == DeriveType::HARDENED)
return false;
414 if (!read_cache->GetCachedParentExtPubKey(m_expr_index, parent_extkey))
return false;
415 final_extkey = parent_extkey;
416 if (m_derive == DeriveType::UNHARDENED) der = parent_extkey.
Derive(final_extkey, pos);
418 }
else if (IsHardened()) {
421 if (!GetDerivedExtKey(arg, xprv, lh_xprv))
return false;
422 parent_extkey = xprv.
Neuter();
423 if (m_derive == DeriveType::UNHARDENED) der = xprv.
Derive(xprv, pos);
424 if (m_derive == DeriveType::HARDENED) der = xprv.
Derive(xprv, pos | 0x80000000UL);
425 final_extkey = xprv.
Neuter();
427 last_hardened_extkey = lh_xprv.
Neuter();
430 for (
auto entry : m_path) {
431 if (!parent_extkey.
Derive(parent_extkey, entry))
return false;
433 final_extkey = parent_extkey;
434 if (m_derive == DeriveType::UNHARDENED) der = parent_extkey.
Derive(final_extkey, pos);
435 assert(m_derive != DeriveType::HARDENED);
437 if (!der)
return false;
439 final_info_out = final_info_out_tmp;
440 key_out = final_extkey.
pubkey;
444 if (m_derive != DeriveType::HARDENED) {
445 write_cache->CacheParentExtPubKey(m_expr_index, parent_extkey);
448 write_cache->CacheLastHardenedExtPubKey(m_expr_index, last_hardened_extkey);
450 }
else if (final_info_out.
path.size() > 0) {
451 write_cache->CacheDerivedExtPubKey(m_expr_index, pos, final_extkey);
457 std::string
ToString(StringType type,
bool normalized)
const 460 const bool use_apostrophe = (!normalized && m_apostrophe) || type == StringType::COMPAT;
464 if (m_derive == DeriveType::HARDENED)
ret += use_apostrophe ?
'\'' :
'h';
468 std::string
ToString(StringType type=StringType::PUBLIC)
const override 475 if (!GetExtKey(arg, key))
return false;
479 if (m_derive == DeriveType::HARDENED)
out += m_apostrophe ?
'\'' :
'h';
485 if (m_derive == DeriveType::HARDENED) {
491 int i = (int)m_path.size() - 1;
492 for (; i >= 0; --i) {
493 if (m_path.at(i) >> 31) {
505 for (;
k <= i; ++
k) {
507 origin.
path.push_back(m_path.at(
k));
511 for (;
k < (int)m_path.size(); ++
k) {
512 end_path.push_back(m_path.at(
k));
515 CKeyID id = m_root_extkey.pubkey.GetID();
516 std::copy(
id.begin(),
id.begin() + 4, origin.
fingerprint);
521 if (cache !=
nullptr) {
527 if (!GetDerivedExtKey(arg, xprv, lh_xprv))
return false;
537 assert(m_derive == DeriveType::UNHARDENED);
545 if (!GetDerivedExtKey(arg, extkey, dummy))
return false;
546 if (m_derive == DeriveType::UNHARDENED && !extkey.
Derive(extkey, pos))
return false;
547 if (m_derive == DeriveType::HARDENED && !extkey.
Derive(extkey, pos | 0x80000000UL))
return false;
551 std::optional<CPubKey> GetRootPubKey()
const override 555 std::optional<CExtPubKey> GetRootExtPubKey()
const override 557 return m_root_extkey;
566 const std::vector<std::unique_ptr<PubkeyProvider>> m_pubkey_args;
568 const std::string m_name;
574 const std::vector<std::unique_ptr<DescriptorImpl>> m_subdescriptor_args;
577 virtual std::string ToStringExtra()
const {
return ""; }
592 DescriptorImpl(std::vector<std::unique_ptr<PubkeyProvider>> pubkeys,
const std::string&
name) : m_pubkey_args(
std::move(pubkeys)), m_name(
name), m_subdescriptor_args() {}
593 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))) {}
594 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)) {}
596 enum class StringType
607 for (
const auto& arg : m_subdescriptor_args) {
608 if (!arg->IsSolvable())
return false;
616 for (
const auto& pubkey : m_pubkey_args) {
617 if (pubkey->IsRange())
return true;
619 for (
const auto& arg : m_subdescriptor_args) {
620 if (arg->IsRange())
return true;
629 for (
const auto& scriptarg : m_subdescriptor_args) {
630 if (pos++)
ret +=
",";
632 if (!scriptarg->ToStringHelper(arg, tmp, type, cache))
return false;
641 std::string extra = ToStringExtra();
642 size_t pos = extra.size() > 0 ? 1 : 0;
643 std::string
ret = m_name +
"(" + extra;
644 for (
const auto& pubkey : m_pubkey_args) {
645 if (pos++)
ret +=
",";
648 case StringType::NORMALIZED:
649 if (!pubkey->ToNormalizedString(*arg, tmp, cache))
return false;
651 case StringType::PRIVATE:
652 if (!pubkey->ToPrivateString(*arg, tmp))
return false;
654 case StringType::PUBLIC:
655 tmp = pubkey->ToString();
657 case StringType::COMPAT:
658 tmp = pubkey->ToString(PubkeyProvider::StringType::COMPAT);
663 std::string subscript;
664 if (!ToStringSubScriptHelper(arg, subscript, type, cache))
return false;
665 if (pos && subscript.size())
ret +=
',';
666 out = std::move(
ret) + std::move(subscript) +
")";
670 std::string
ToString(
bool compat_format)
const final 673 ToStringHelper(
nullptr,
ret, compat_format ? StringType::COMPAT : StringType::PUBLIC);
674 return AddChecksum(
ret);
679 bool ret = ToStringHelper(&arg,
out, StringType::PRIVATE);
686 bool ret = ToStringHelper(&arg,
out, StringType::NORMALIZED, cache);
694 std::vector<std::pair<CPubKey, KeyOriginInfo>> entries;
695 entries.reserve(m_pubkey_args.size());
698 for (
const auto& p : m_pubkey_args) {
699 entries.emplace_back();
700 if (!p->GetPubKey(pos, arg, entries.back().first, entries.back().second, read_cache, write_cache))
return false;
702 std::vector<CScript> subscripts;
704 for (
const auto& subarg : m_subdescriptor_args) {
705 std::vector<CScript> outscripts;
706 if (!subarg->ExpandHelper(pos, arg, read_cache, outscripts, subprovider, write_cache))
return false;
707 assert(outscripts.size() == 1);
708 subscripts.emplace_back(std::move(outscripts[0]));
710 out.Merge(std::move(subprovider));
712 std::vector<CPubKey> pubkeys;
713 pubkeys.reserve(entries.size());
714 for (
auto& entry : entries) {
715 pubkeys.push_back(entry.first);
716 out.origins.emplace(entry.first.GetID(), std::make_pair<CPubKey, KeyOriginInfo>(
CPubKey(entry.first), std::move(entry.second)));
719 output_scripts = MakeScripts(pubkeys,
Span{subscripts},
out);
725 return ExpandHelper(pos, provider,
nullptr, output_scripts,
out, write_cache);
736 for (
const auto& p : m_pubkey_args) {
738 if (!p->GetPrivKey(pos, provider, key))
continue;
741 for (
const auto& arg : m_subdescriptor_args) {
742 arg->ExpandPrivate(pos, provider,
out);
746 std::optional<OutputType>
GetOutputType()
const override {
return std::nullopt; }
748 std::optional<int64_t>
ScriptSize()
const override {
return {}; }
755 virtual std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const {
return {}; }
762 void GetPubKeys(std::set<CPubKey>& pubkeys, std::set<CExtPubKey>& ext_pubs)
const override 764 for (
const auto& p : m_pubkey_args) {
765 std::optional<CPubKey> pub = p->GetRootPubKey();
766 if (pub) pubkeys.insert(*pub);
767 std::optional<CExtPubKey> ext_pub = p->GetRootExtPubKey();
768 if (ext_pub) ext_pubs.insert(*ext_pub);
770 for (
const auto& arg : m_subdescriptor_args) {
771 arg->GetPubKeys(pubkeys, ext_pubs);
777 class AddressDescriptor final :
public DescriptorImpl
781 std::string ToStringExtra()
const override {
return EncodeDestination(m_destination); }
784 AddressDescriptor(
CTxDestination destination) : DescriptorImpl({},
"addr"), m_destination(std::move(destination)) {}
785 bool IsSolvable() const final {
return false; }
791 bool IsSingleType() const final {
return true; }
792 bool ToPrivateString(
const SigningProvider& arg, std::string&
out)
const final {
return false; }
798 class RawDescriptor final :
public DescriptorImpl
802 std::string ToStringExtra()
const override {
return HexStr(m_script); }
806 bool IsSolvable() const final {
return false; }
814 bool IsSingleType() const final {
return true; }
815 bool ToPrivateString(
const SigningProvider& arg, std::string&
out)
const final {
return false; }
817 std::optional<int64_t> ScriptSize()
const override {
return m_script.size(); }
821 class PKDescriptor final :
public DescriptorImpl
836 PKDescriptor(std::unique_ptr<PubkeyProvider> prov,
bool xonly =
false) : DescriptorImpl(
Vector(
std::move(prov)),
"pk"), m_xonly(xonly) {}
837 bool IsSingleType() const final {
return true; }
839 std::optional<int64_t> ScriptSize()
const override {
840 return 1 + (m_xonly ? 32 : m_pubkey_args[0]->GetSize()) + 1;
843 std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const override {
844 const auto ecdsa_sig_size = use_max_sig ? 72 : 71;
845 return 1 + (m_xonly ? 65 : ecdsa_sig_size);
848 std::optional<int64_t> MaxSatisfactionWeight(
bool use_max_sig)
const override {
852 std::optional<int64_t> MaxSatisfactionElems()
const override {
return 1; }
856 class PKHDescriptor final :
public DescriptorImpl
861 CKeyID id = keys[0].GetID();
862 out.pubkeys.emplace(
id, keys[0]);
866 PKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(
Vector(
std::move(prov)),
"pkh") {}
868 bool IsSingleType() const final {
return true; }
870 std::optional<int64_t> ScriptSize()
const override {
return 1 + 1 + 1 + 20 + 1 + 1; }
872 std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const override {
873 const auto sig_size = use_max_sig ? 72 : 71;
874 return 1 +
sig_size + 1 + m_pubkey_args[0]->GetSize();
877 std::optional<int64_t> MaxSatisfactionWeight(
bool use_max_sig)
const override {
881 std::optional<int64_t> MaxSatisfactionElems()
const override {
return 2; }
885 class WPKHDescriptor final :
public DescriptorImpl
890 CKeyID id = keys[0].GetID();
891 out.pubkeys.emplace(
id, keys[0]);
895 WPKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(
Vector(
std::move(prov)),
"wpkh") {}
897 bool IsSingleType() const final {
return true; }
899 std::optional<int64_t> ScriptSize()
const override {
return 1 + 1 + 20; }
901 std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const override {
902 const auto sig_size = use_max_sig ? 72 : 71;
906 std::optional<int64_t> MaxSatisfactionWeight(
bool use_max_sig)
const override {
907 return MaxSatSize(use_max_sig);
910 std::optional<int64_t> MaxSatisfactionElems()
const override {
return 2; }
914 class ComboDescriptor final :
public DescriptorImpl
919 std::vector<CScript>
ret;
920 CKeyID id = keys[0].GetID();
921 out.pubkeys.emplace(
id, keys[0]);
924 if (keys[0].IsCompressed()) {
927 ret.emplace_back(p2wpkh);
933 ComboDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(
Vector(
std::move(prov)),
"combo") {}
934 bool IsSingleType() const final {
return false; }
938 class MultisigDescriptor final :
public DescriptorImpl
940 const int m_threshold;
943 std::string ToStringExtra()
const override {
return strprintf(
"%i", m_threshold); }
946 std::vector<CPubKey> sorted_keys(keys);
947 std::sort(sorted_keys.begin(), sorted_keys.end());
953 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) {}
954 bool IsSingleType() const final {
return true; }
956 std::optional<int64_t> ScriptSize()
const override {
957 const auto n_keys = m_pubkey_args.size();
958 auto op = [](int64_t acc,
const std::unique_ptr<PubkeyProvider>&
pk) {
return acc + 1 +
pk->GetSize();};
959 const auto pubkeys_size{std::accumulate(m_pubkey_args.begin(), m_pubkey_args.end(), int64_t{0}, op)};
963 std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const override {
964 const auto sig_size = use_max_sig ? 72 : 71;
965 return (1 + (1 +
sig_size) * m_threshold);
968 std::optional<int64_t> MaxSatisfactionWeight(
bool use_max_sig)
const override {
972 std::optional<int64_t> MaxSatisfactionElems()
const override {
return 1 + m_threshold; }
976 class MultiADescriptor final :
public DescriptorImpl
978 const int m_threshold;
981 std::string ToStringExtra()
const override {
return strprintf(
"%i", m_threshold); }
984 std::vector<XOnlyPubKey> xkeys;
985 xkeys.reserve(keys.size());
986 for (
const auto& key : keys) xkeys.emplace_back(key);
987 if (m_sorted) std::sort(xkeys.begin(), xkeys.end());
989 for (
size_t i = 1; i < keys.size(); ++i) {
996 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) {}
997 bool IsSingleType() const final {
return true; }
999 std::optional<int64_t> ScriptSize()
const override {
1000 const auto n_keys = m_pubkey_args.size();
1004 std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const override {
1005 return (1 + 65) * m_threshold + (m_pubkey_args.size() - m_threshold);
1008 std::optional<int64_t> MaxSatisfactionElems()
const override {
return m_pubkey_args.size(); }
1012 class SHDescriptor final :
public DescriptorImpl
1018 if (
ret.size())
out.scripts.emplace(
CScriptID(scripts[0]), scripts[0]);
1025 SHDescriptor(std::unique_ptr<DescriptorImpl> desc) : DescriptorImpl({}, std::move(desc),
"sh") {}
1029 assert(m_subdescriptor_args.size() == 1);
1033 bool IsSingleType() const final {
return true; }
1035 std::optional<int64_t> ScriptSize()
const override {
return 1 + 1 + 20 + 1; }
1037 std::optional<int64_t> MaxSatisfactionWeight(
bool use_max_sig)
const override {
1038 if (
const auto sat_size = m_subdescriptor_args[0]->MaxSatSize(use_max_sig)) {
1039 if (
const auto subscript_size = m_subdescriptor_args[0]->ScriptSize()) {
1043 if (
IsSegwit())
return subscript_weight + *sat_size;
1050 std::optional<int64_t> MaxSatisfactionElems()
const override {
1051 if (
const auto sub_elems = m_subdescriptor_args[0]->MaxSatisfactionElems())
return 1 + *sub_elems;
1057 class WSHDescriptor final :
public DescriptorImpl
1063 if (
ret.size())
out.scripts.emplace(
CScriptID(scripts[0]), scripts[0]);
1067 WSHDescriptor(std::unique_ptr<DescriptorImpl> desc) : DescriptorImpl({}, std::move(desc),
"wsh") {}
1069 bool IsSingleType() const final {
return true; }
1071 std::optional<int64_t> ScriptSize()
const override {
return 1 + 1 + 32; }
1073 std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const override {
1074 if (
const auto sat_size = m_subdescriptor_args[0]->MaxSatSize(use_max_sig)) {
1075 if (
const auto subscript_size = m_subdescriptor_args[0]->ScriptSize()) {
1082 std::optional<int64_t> MaxSatisfactionWeight(
bool use_max_sig)
const override {
1083 return MaxSatSize(use_max_sig);
1086 std::optional<int64_t> MaxSatisfactionElems()
const override {
1087 if (
const auto sub_elems = m_subdescriptor_args[0]->MaxSatisfactionElems())
return 1 + *sub_elems;
1093 class TRDescriptor final :
public DescriptorImpl
1095 std::vector<int> m_depths;
1101 for (
size_t pos = 0; pos < m_depths.size(); ++pos) {
1105 assert(keys.size() == 1);
1107 if (!xpk.IsFullyValid())
return {};
1110 out.tr_trees[output] = builder;
1111 out.pubkeys.emplace(keys[0].GetID(), keys[0]);
1116 if (m_depths.empty())
return true;
1117 std::vector<bool> path;
1118 for (
size_t pos = 0; pos < m_depths.size(); ++pos) {
1119 if (pos)
ret +=
',';
1120 while ((
int)path.size() <= m_depths[pos]) {
1121 if (path.size())
ret +=
'{';
1122 path.push_back(
false);
1125 if (!m_subdescriptor_args[pos]->ToStringHelper(arg, tmp, type, cache))
return false;
1127 while (!path.empty() && path.back()) {
1128 if (path.size() > 1)
ret +=
'}';
1131 if (!path.empty()) path.back() =
true;
1136 TRDescriptor(std::unique_ptr<PubkeyProvider> internal_key, std::vector<std::unique_ptr<DescriptorImpl>> descs, std::vector<int> depths) :
1137 DescriptorImpl(
Vector(
std::move(internal_key)),
std::move(descs),
"tr"), m_depths(
std::move(depths))
1139 assert(m_subdescriptor_args.size() == m_depths.size());
1142 bool IsSingleType() const final {
return true; }
1144 std::optional<int64_t> ScriptSize()
const override {
return 1 + 1 + 32; }
1146 std::optional<int64_t> MaxSatisfactionWeight(
bool)
const override {
1151 std::optional<int64_t> MaxSatisfactionElems()
const override {
1167 const std::vector<CPubKey>& m_keys;
1174 uint160 GetHash160(uint32_t key)
const {
1178 return m_keys[key].GetID();
1184 std::vector<unsigned char> ToPKBytes(uint32_t key)
const {
1187 return {m_keys[key].begin(), m_keys[key].end()};
1190 return {xonly_pubkey.
begin(), xonly_pubkey.end()};
1193 std::vector<unsigned char> ToPKHBytes(uint32_t key)
const {
1194 auto id = GetHash160(key);
1195 return {
id.begin(),
id.end()};
1206 const std::vector<std::unique_ptr<PubkeyProvider>>& m_pubkeys;
1212 : m_arg(arg), m_pubkeys(pubkeys), m_private(priv) {}
1214 std::optional<std::string>
ToString(uint32_t key)
const 1218 if (!m_pubkeys[key]->ToPrivateString(*m_arg,
ret))
return {};
1220 ret = m_pubkeys[key]->ToString();
1226 class MiniscriptDescriptor final :
public DescriptorImpl
1232 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>& keys,
Span<const CScript> scripts,
1235 const auto script_ctx{
m_node->GetMsCtx()};
1236 for (
const auto& key : keys) {
1240 provider.
pubkeys.emplace(key.GetID(), key);
1243 return Vector(
m_node->ToScript(ScriptMaker(keys, script_ctx)));
1250 bool ToStringHelper(
const SigningProvider* arg, std::string&
out,
const StringType type,
1253 if (
const auto res =
m_node->ToString(StringMaker(arg, m_pubkey_args, type == StringType::PRIVATE))) {
1260 bool IsSolvable()
const override {
return true; }
1261 bool IsSingleType() const final {
return true; }
1263 std::optional<int64_t> ScriptSize()
const override {
return m_node->ScriptSize(); }
1265 std::optional<int64_t> MaxSatSize(
bool)
const override {
1267 return m_node->GetWitnessSize();
1270 std::optional<int64_t> MaxSatisfactionElems()
const override {
1271 return m_node->GetStackSize();
1276 class RawTRDescriptor final :
public DescriptorImpl
1281 assert(keys.size() == 1);
1283 if (!xpk.IsFullyValid())
return {};
1288 RawTRDescriptor(std::unique_ptr<PubkeyProvider> output_key) : DescriptorImpl(
Vector(
std::move(output_key)),
"rawtr") {}
1290 bool IsSingleType() const final {
return true; }
1292 std::optional<int64_t> ScriptSize()
const override {
return 1 + 1 + 32; }
1294 std::optional<int64_t> MaxSatisfactionWeight(
bool)
const override {
1299 std::optional<int64_t> MaxSatisfactionElems()
const override {
1326 [[nodiscard]]
bool ParseKeyPath(
const std::vector<
Span<const char>>&
split, KeyPath&
out,
bool& apostrophe, std::string& error)
1328 for (
size_t i = 1; i <
split.size(); ++i) {
1330 bool hardened =
false;
1331 if (elem.
size() > 0) {
1332 const char last = elem[elem.
size() - 1];
1333 if (last ==
'\'' || last ==
'h') {
1336 apostrophe = last ==
'\'';
1341 error =
strprintf(
"Key path value '%s' is not a valid uint32", std::string(elem.
begin(), elem.
end()));
1343 }
else if (p > 0x7FFFFFFFUL) {
1344 error =
strprintf(
"Key path value %u is out of range", p);
1347 out.push_back(p | (((uint32_t)hardened) << 31));
1355 bool permit_uncompressed = ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH;
1357 std::string str(
split[0].begin(),
split[0].end());
1358 if (str.size() == 0) {
1359 error =
"No key provided";
1362 if (
split.size() == 1) {
1364 std::vector<unsigned char> data =
ParseHex(str);
1366 if (pubkey.IsValid() && !pubkey.IsValidNonHybrid()) {
1367 error =
"Hybrid public keys are not allowed";
1370 if (pubkey.IsFullyValid()) {
1371 if (permit_uncompressed || pubkey.IsCompressed()) {
1372 return std::make_unique<ConstPubkeyProvider>(key_exp_index, pubkey,
false);
1374 error =
"Uncompressed keys are not allowed";
1377 }
else if (data.size() == 32 && ctx == ParseScriptContext::P2TR) {
1378 unsigned char fullkey[33] = {0x02};
1379 std::copy(data.begin(), data.end(), fullkey + 1);
1380 pubkey.Set(std::begin(fullkey), std::end(fullkey));
1381 if (pubkey.IsFullyValid()) {
1382 return std::make_unique<ConstPubkeyProvider>(key_exp_index, pubkey,
true);
1385 error =
strprintf(
"Pubkey '%s' is invalid", str);
1392 out.keys.emplace(pubkey.
GetID(), key);
1393 return std::make_unique<ConstPubkeyProvider>(key_exp_index, pubkey, ctx == ParseScriptContext::P2TR);
1395 error =
"Uncompressed keys are not allowed";
1403 error =
strprintf(
"key '%s' is not valid", str);
1410 type = DeriveType::UNHARDENED;
1414 type = DeriveType::HARDENED;
1416 if (!ParseKeyPath(
split, path, apostrophe, error))
return nullptr;
1418 extpubkey = extkey.
Neuter();
1421 return std::make_unique<BIP32PubkeyProvider>(key_exp_index, extpubkey, std::move(path), type, apostrophe);
1427 auto origin_split =
Split(sp,
']');
1428 if (origin_split.size() > 2) {
1429 error =
"Multiple ']' characters found for a single pubkey";
1433 bool apostrophe =
false;
1434 if (origin_split.size() == 1) {
1435 return ParsePubkeyInner(key_exp_index, origin_split[0], ctx,
out, apostrophe, error);
1437 if (origin_split[0].empty() || origin_split[0][0] !=
'[') {
1438 error =
strprintf(
"Key origin start '[ character expected but not found, got '%c' instead",
1439 origin_split[0].empty() ?
']' : origin_split[0][0]);
1442 auto slash_split =
Split(origin_split[0].subspan(1),
'/');
1443 if (slash_split[0].size() != 8) {
1444 error =
strprintf(
"Fingerprint is not 4 bytes (%u characters instead of 8 characters)", slash_split[0].size());
1447 std::string fpr_hex = std::string(slash_split[0].begin(), slash_split[0].end());
1448 if (!
IsHex(fpr_hex)) {
1449 error =
strprintf(
"Fingerprint '%s' is not hex", fpr_hex);
1452 auto fpr_bytes =
ParseHex(fpr_hex);
1454 static_assert(
sizeof(info.
fingerprint) == 4,
"Fingerprint must be 4 bytes");
1455 assert(fpr_bytes.size() == 4);
1456 std::copy(fpr_bytes.begin(), fpr_bytes.end(), info.
fingerprint);
1457 if (!ParseKeyPath(slash_split, info.
path, apostrophe, error))
return nullptr;
1458 auto provider = ParsePubkeyInner(key_exp_index, origin_split[1], ctx,
out, apostrophe, error);
1459 if (!provider)
return nullptr;
1460 return std::make_unique<OriginPubkeyProvider>(key_exp_index, std::move(info), std::move(provider), apostrophe);
1470 if (ctx != ParseScriptContext::TOP && ctx != ParseScriptContext::P2SH && !pubkey.
IsCompressed()) {
1473 std::unique_ptr<PubkeyProvider> key_provider = std::make_unique<ConstPubkeyProvider>(0, pubkey,
false);
1476 return std::make_unique<OriginPubkeyProvider>(0, std::move(info), std::move(key_provider),
false);
1478 return key_provider;
1484 std::unique_ptr<PubkeyProvider> key_provider = std::make_unique<ConstPubkeyProvider>(0, pubkey,
true);
1487 return std::make_unique<OriginPubkeyProvider>(0, std::move(info), std::move(key_provider),
false);
1489 return key_provider;
1497 using Key = uint32_t;
1503 mutable std::vector<std::unique_ptr<PubkeyProvider>> m_keys;
1505 mutable std::string m_key_parsing_error;
1513 : m_out(
out), m_in(in), m_script_ctx(ctx), m_offset(offset) {}
1515 bool KeyCompare(
const Key& a,
const Key& b)
const {
1516 return *m_keys.at(a) < *m_keys.at(b);
1520 switch (m_script_ctx) {
1527 template<
typename I> std::optional<Key>
FromString(I begin, I end)
const 1530 Key key = m_keys.
size();
1531 auto pk = ParsePubkey(m_offset + key, {&*begin, &*end},
ParseContext(), *m_out, m_key_parsing_error);
1533 m_keys.push_back(std::move(
pk));
1537 std::optional<std::string>
ToString(
const Key& key)
const 1539 return m_keys.at(key)->ToString();
1542 template<
typename I> std::optional<Key> FromPKBytes(I begin, I end)
const 1545 Key key = m_keys.size();
1548 std::copy(begin, end, pubkey.
begin());
1550 m_keys.push_back(std::move(pubkey_provider));
1555 if (
auto pubkey_provider = InferPubkey(pubkey,
ParseContext(), *m_in)) {
1556 m_keys.push_back(std::move(pubkey_provider));
1563 template<
typename I> std::optional<Key> FromPKHBytes(I begin, I end)
const 1565 assert(end - begin == 20);
1568 std::copy(begin, end, hash.
begin());
1572 if (
auto pubkey_provider = InferPubkey(pubkey,
ParseContext(), *m_in)) {
1573 Key key = m_keys.
size();
1574 m_keys.push_back(std::move(pubkey_provider));
1582 return m_script_ctx;
1592 auto expr =
Expr(sp);
1593 if (
Func(
"pk", expr)) {
1594 auto pubkey = ParsePubkey(key_exp_index, expr, ctx,
out, error);
1600 return std::make_unique<PKDescriptor>(std::move(pubkey), ctx == ParseScriptContext::P2TR);
1602 if ((ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH) &&
Func(
"pkh", expr)) {
1603 auto pubkey = ParsePubkey(key_exp_index, expr, ctx,
out, error);
1609 return std::make_unique<PKHDescriptor>(std::move(pubkey));
1610 }
else if (ctx != ParseScriptContext::P2TR &&
Func(
"pkh", expr)) {
1612 error =
"Can only have pkh at top level, in sh(), wsh(), or in tr()";
1615 if (ctx == ParseScriptContext::TOP &&
Func(
"combo", expr)) {
1616 auto pubkey = ParsePubkey(key_exp_index, expr, ctx,
out, error);
1618 error =
strprintf(
"combo(): %s", error);
1622 return std::make_unique<ComboDescriptor>(std::move(pubkey));
1623 }
else if (
Func(
"combo", expr)) {
1624 error =
"Can only have combo() at top level";
1627 const bool multi =
Func(
"multi", expr);
1628 const bool sortedmulti = !multi &&
Func(
"sortedmulti", expr);
1629 const bool multi_a = !(multi || sortedmulti) &&
Func(
"multi_a", expr);
1630 const bool sortedmulti_a = !(multi || sortedmulti || multi_a) &&
Func(
"sortedmulti_a", expr);
1631 if (((ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH) && (multi || sortedmulti)) ||
1632 (ctx == ParseScriptContext::P2TR && (multi_a || sortedmulti_a))) {
1633 auto threshold =
Expr(expr);
1635 std::vector<std::unique_ptr<PubkeyProvider>> providers;
1636 if (!
ParseUInt32(std::string(threshold.begin(), threshold.end()), &thres)) {
1637 error =
strprintf(
"Multi threshold '%s' is not valid", std::string(threshold.begin(), threshold.end()));
1640 size_t script_size = 0;
1641 while (expr.size()) {
1642 if (!
Const(
",", expr)) {
1643 error =
strprintf(
"Multi: expected ',', got '%c'", expr[0]);
1646 auto arg =
Expr(expr);
1647 auto pk = ParsePubkey(key_exp_index, arg, ctx,
out, error);
1652 script_size +=
pk->GetSize() + 1;
1653 providers.emplace_back(std::move(
pk));
1662 }
else if (thres < 1) {
1663 error =
strprintf(
"Multisig threshold cannot be %d, must be at least 1", thres);
1665 }
else if (thres > providers.size()) {
1666 error =
strprintf(
"Multisig threshold cannot be larger than the number of keys; threshold is %d but only %u keys specified", thres, providers.size());
1669 if (ctx == ParseScriptContext::TOP) {
1670 if (providers.size() > 3) {
1671 error =
strprintf(
"Cannot have %u pubkeys in bare multisig; only at most 3 pubkeys", providers.size());
1675 if (ctx == ParseScriptContext::P2SH) {
1682 if (multi || sortedmulti) {
1683 return std::make_unique<MultisigDescriptor>(thres, std::move(providers), sortedmulti);
1685 return std::make_unique<MultiADescriptor>(thres, std::move(providers), sortedmulti_a);
1687 }
else if (multi || sortedmulti) {
1688 error =
"Can only have multi/sortedmulti at top level, in sh(), or in wsh()";
1690 }
else if (multi_a || sortedmulti_a) {
1691 error =
"Can only have multi_a/sortedmulti_a inside tr()";
1694 if ((ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH) &&
Func(
"wpkh", expr)) {
1695 auto pubkey = ParsePubkey(key_exp_index, expr, ParseScriptContext::P2WPKH,
out, error);
1701 return std::make_unique<WPKHDescriptor>(std::move(pubkey));
1702 }
else if (
Func(
"wpkh", expr)) {
1703 error =
"Can only have wpkh() at top level or inside sh()";
1706 if (ctx == ParseScriptContext::TOP &&
Func(
"sh", expr)) {
1707 auto desc =
ParseScript(key_exp_index, expr, ParseScriptContext::P2SH,
out, error);
1708 if (!desc || expr.size())
return nullptr;
1709 return std::make_unique<SHDescriptor>(std::move(desc));
1710 }
else if (
Func(
"sh", expr)) {
1711 error =
"Can only have sh() at top level";
1714 if ((ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH) &&
Func(
"wsh", expr)) {
1715 auto desc =
ParseScript(key_exp_index, expr, ParseScriptContext::P2WSH,
out, error);
1716 if (!desc || expr.size())
return nullptr;
1717 return std::make_unique<WSHDescriptor>(std::move(desc));
1718 }
else if (
Func(
"wsh", expr)) {
1719 error =
"Can only have wsh() at top level or inside sh()";
1722 if (ctx == ParseScriptContext::TOP &&
Func(
"addr", expr)) {
1725 error =
"Address is not valid";
1728 return std::make_unique<AddressDescriptor>(std::move(dest));
1729 }
else if (
Func(
"addr", expr)) {
1730 error =
"Can only have addr() at top level";
1733 if (ctx == ParseScriptContext::TOP &&
Func(
"tr", expr)) {
1734 auto arg =
Expr(expr);
1735 auto internal_key = ParsePubkey(key_exp_index, arg, ParseScriptContext::P2TR,
out, error);
1736 if (!internal_key) {
1741 std::vector<std::unique_ptr<DescriptorImpl>> subscripts;
1742 std::vector<int> depths;
1744 if (!
Const(
",", expr)) {
1745 error =
strprintf(
"tr: expected ',', got '%c'", expr[0]);
1751 std::vector<bool> branches;
1756 while (
Const(
"{", expr)) {
1757 branches.push_back(
false);
1764 auto sarg =
Expr(expr);
1765 subscripts.emplace_back(
ParseScript(key_exp_index, sarg, ParseScriptContext::P2TR,
out, error));
1766 if (!subscripts.back())
return nullptr;
1767 depths.push_back(branches.size());
1769 while (branches.size() && branches.back()) {
1770 if (!
Const(
"}", expr)) {
1771 error =
strprintf(
"tr(): expected '}' after script expression");
1774 branches.pop_back();
1777 if (branches.size() && !branches.back()) {
1778 if (!
Const(
",", expr)) {
1779 error =
strprintf(
"tr(): expected ',' after script expression");
1782 branches.back() =
true;
1784 }
while (branches.size());
1787 error =
strprintf(
"tr(): expected ')' after script expression");
1792 return std::make_unique<TRDescriptor>(std::move(internal_key), std::move(subscripts), std::move(depths));
1793 }
else if (
Func(
"tr", expr)) {
1794 error =
"Can only have tr at top level";
1797 if (ctx == ParseScriptContext::TOP &&
Func(
"rawtr", expr)) {
1798 auto arg =
Expr(expr);
1800 error =
strprintf(
"rawtr(): only one key expected.");
1803 auto output_key = ParsePubkey(key_exp_index, arg, ParseScriptContext::P2TR,
out, error);
1804 if (!output_key)
return nullptr;
1806 return std::make_unique<RawTRDescriptor>(std::move(output_key));
1807 }
else if (
Func(
"rawtr", expr)) {
1808 error =
"Can only have rawtr at top level";
1811 if (ctx == ParseScriptContext::TOP &&
Func(
"raw", expr)) {
1812 std::string str(expr.begin(), expr.end());
1814 error =
"Raw script is not hex";
1818 return std::make_unique<RawDescriptor>(
CScript(bytes.begin(), bytes.end()));
1819 }
else if (
Func(
"raw", expr)) {
1820 error =
"Can only have raw() at top level";
1826 KeyParser parser(&
out,
nullptr, script_ctx, key_exp_index);
1828 if (parser.m_key_parsing_error !=
"") {
1829 error = std::move(parser.m_key_parsing_error);
1833 if (ctx != ParseScriptContext::P2WSH && ctx != ParseScriptContext::P2TR) {
1834 error =
"Miniscript expressions can only be used in wsh or tr.";
1837 if (!
node->IsSane() ||
node->IsNotSatisfiable()) {
1839 auto insane_node =
node.get();
1840 if (
const auto sub =
node->FindInsaneSub()) insane_node = sub;
1841 if (
const auto str = insane_node->ToString(parser)) error = *str;
1842 if (!insane_node->IsValid()) {
1843 error +=
" is invalid";
1844 }
else if (!
node->IsSane()) {
1845 error +=
" is not sane";
1846 if (!insane_node->IsNonMalleable()) {
1847 error +=
": malleable witnesses exist";
1848 }
else if (insane_node ==
node.get() && !insane_node->NeedsSignature()) {
1849 error +=
": witnesses without signature exist";
1850 }
else if (!insane_node->CheckTimeLocksMix()) {
1851 error +=
": contains mixes of timelocks expressed in blocks and seconds";
1852 }
else if (!insane_node->CheckDuplicateKey()) {
1853 error +=
": contains duplicate public keys";
1854 }
else if (!insane_node->ValidSatisfactions()) {
1855 error +=
": needs witnesses that may exceed resource limits";
1858 error +=
" is not satisfiable";
1865 key_exp_index += parser.m_keys.size();
1866 return std::make_unique<MiniscriptDescriptor>(std::move(parser.m_keys), std::move(
node));
1869 if (ctx == ParseScriptContext::P2SH) {
1870 error =
"A function is needed within P2SH";
1872 }
else if (ctx == ParseScriptContext::P2WSH) {
1873 error =
"A function is needed within P2WSH";
1876 error =
strprintf(
"'%s' is not a valid descriptor function", std::string(expr.begin(), expr.end()));
1883 if (!match)
return {};
1884 std::vector<std::unique_ptr<PubkeyProvider>> keys;
1885 keys.reserve(match->second.size());
1886 for (
const auto keyspan : match->second) {
1887 if (keyspan.size() != 32)
return {};
1888 auto key = InferXOnlyPubkey(
XOnlyPubKey{keyspan}, ctx, provider);
1889 if (!key)
return {};
1890 keys.push_back(std::move(key));
1892 return std::make_unique<MultiADescriptor>(match->first, std::move(keys));
1900 return std::make_unique<PKDescriptor>(InferXOnlyPubkey(key, ctx, provider),
true);
1903 if (ctx == ParseScriptContext::P2TR) {
1904 auto ret = InferMultiA(
script, ctx, provider);
1908 std::vector<std::vector<unsigned char>> data;
1911 if (txntype ==
TxoutType::PUBKEY && (ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH)) {
1913 if (
auto pubkey_provider = InferPubkey(pubkey, ctx, provider)) {
1914 return std::make_unique<PKDescriptor>(std::move(pubkey_provider));
1917 if (txntype ==
TxoutType::PUBKEYHASH && (ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH)) {
1921 if (provider.
GetPubKey(keyid, pubkey)) {
1922 if (
auto pubkey_provider = InferPubkey(pubkey, ctx, provider)) {
1923 return std::make_unique<PKHDescriptor>(std::move(pubkey_provider));
1931 if (provider.
GetPubKey(keyid, pubkey)) {
1932 if (
auto pubkey_provider = InferPubkey(pubkey, ParseScriptContext::P2WPKH, provider)) {
1933 return std::make_unique<WPKHDescriptor>(std::move(pubkey_provider));
1937 if (txntype ==
TxoutType::MULTISIG && (ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH)) {
1939 std::vector<std::unique_ptr<PubkeyProvider>> providers;
1940 for (
size_t i = 1; i + 1 < data.size(); ++i) {
1942 if (
auto pubkey_provider = InferPubkey(pubkey, ctx, provider)) {
1943 providers.push_back(std::move(pubkey_provider));
1949 if (ok)
return std::make_unique<MultisigDescriptor>((int)data[0][0], std::move(providers));
1955 if (provider.
GetCScript(scriptid, subscript)) {
1956 auto sub = InferScript(subscript, ParseScriptContext::P2SH, provider);
1957 if (sub)
return std::make_unique<SHDescriptor>(std::move(sub));
1963 if (provider.
GetCScript(scriptid, subscript)) {
1964 auto sub = InferScript(subscript, ParseScriptContext::P2WSH, provider);
1965 if (sub)
return std::make_unique<WSHDescriptor>(std::move(sub));
1971 std::copy(data[0].begin(), data[0].end(), pubkey.
begin());
1980 std::vector<std::unique_ptr<DescriptorImpl>> subscripts;
1981 std::vector<int> depths;
1982 for (
const auto& [depth,
script, leaf_ver] : *tree) {
1983 std::unique_ptr<DescriptorImpl> subdesc;
1985 subdesc = InferScript(
CScript(
script.begin(),
script.end()), ParseScriptContext::P2TR, provider);
1991 subscripts.push_back(std::move(subdesc));
1992 depths.push_back(depth);
1996 auto key = InferXOnlyPubkey(tap.internal_key, ParseScriptContext::P2TR, provider);
1997 return std::make_unique<TRDescriptor>(std::move(key), std::move(subscripts), std::move(depths));
2003 auto key = InferXOnlyPubkey(pubkey, ParseScriptContext::P2TR, provider);
2005 return std::make_unique<RawTRDescriptor>(std::move(key));
2010 if (ctx == ParseScriptContext::P2WSH || ctx == ParseScriptContext::P2TR) {
2012 KeyParser parser(
nullptr, &provider, script_ctx);
2015 return std::make_unique<MiniscriptDescriptor>(std::move(parser.m_keys), std::move(
node));
2021 if (ctx != ParseScriptContext::TOP)
return nullptr;
2026 return std::make_unique<AddressDescriptor>(std::move(dest));
2030 return std::make_unique<RawDescriptor>(
script);
2039 auto check_split =
Split(sp,
'#');
2040 if (check_split.size() > 2) {
2041 error =
"Multiple '#' symbols";
2044 if (check_split.size() == 1 && require_checksum){
2045 error =
"Missing checksum";
2048 if (check_split.size() == 2) {
2049 if (check_split[1].size() != 8) {
2050 error =
strprintf(
"Expected 8 character checksum, not %u characters", check_split[1].size());
2054 auto checksum = DescriptorChecksum(check_split[0]);
2055 if (checksum.empty()) {
2056 error =
"Invalid characters in payload";
2059 if (check_split.size() == 2) {
2060 if (!std::equal(checksum.begin(), checksum.end(), check_split[1].begin())) {
2061 error =
strprintf(
"Provided checksum '%s' does not match computed checksum '%s'", std::string(check_split[1].begin(), check_split[1].end()), checksum);
2065 if (out_checksum) *out_checksum = std::move(checksum);
2066 sp = check_split[0];
2073 if (!
CheckChecksum(sp, require_checksum, error))
return nullptr;
2074 uint32_t key_exp_index = 0;
2076 if (sp.
size() == 0 &&
ret)
return std::unique_ptr<Descriptor>(std::move(
ret));
2091 return InferScript(
script, ParseScriptContext::TOP, provider);
2096 std::string desc_str = desc.
ToString(
true);
2098 CSHA256().
Write((
unsigned char*)desc_str.data(), desc_str.size()).Finalize(
id.begin());
2110 xpubs[der_index] = xpub;
2130 const auto& der_it = key_exp_it->second.find(der_index);
2131 if (der_it == key_exp_it->second.end())
return false;
2132 xpub = der_it->second;
2150 if (xpub != parent_xpub_pair.second) {
2151 throw std::runtime_error(std::string(__func__) +
": New cached parent xpub does not match already cached parent xpub");
2159 for (
const auto& derived_xpub_pair : derived_xpub_map_pair.second) {
2162 if (xpub != derived_xpub_pair.second) {
2163 throw std::runtime_error(std::string(__func__) +
": New cached derived xpub does not match already cached derived xpub");
2167 CacheDerivedExtPubKey(derived_xpub_map_pair.first, derived_xpub_pair.first, derived_xpub_pair.second);
2168 diff.
CacheDerivedExtPubKey(derived_xpub_map_pair.first, derived_xpub_pair.first, derived_xpub_pair.second);
2174 if (xpub != lh_xpub_pair.second) {
2175 throw std::runtime_error(std::string(__func__) +
": New cached last hardened xpub does not match already cached last hardened xpub");
CScript BuildScript(Ts &&... inputs)
Build a script by concatenating other scripts, or any argument accepted by CScript::operator<<.
std::unordered_map< uint32_t, ExtPubKeyMap > GetCachedDerivedExtPubKeys() const
Retrieve all cached derived xpubs.
NodeRef< typename Ctx::Key > FromString(const std::string &str, const Ctx &ctx)
bool CheckChecksum(Span< const char > &sp, bool require_checksum, std::string &error, std::string *out_checksum=nullptr)
Check a descriptor checksum, and update desc to be the checksum-less part.
CSHA256 & Write(const unsigned char *data, size_t len)
CONSTEXPR_IF_NOT_DEBUG Span< C > first(std::size_t count) const noexcept
CScript GetScriptForMultisig(int nRequired, const std::vector< CPubKey > &keys)
Generate a multisig script.
ExtPubKeyMap m_last_hardened_xpubs
Map key expression index -> last hardened xpub.
static constexpr size_t size()
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.
unsigned char fingerprint[4]
First 32 bits of the Hash160 of the public key at the root of the path.
ExtPubKeyMap GetCachedParentExtPubKeys() const
Retrieve all cached parent xpubs.
std::vector< Byte > ParseHex(std::string_view hex_str)
Like TryParseHex, but returns an empty vector on invalid input.
static const int WITNESS_SCALE_FACTOR
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination corresponds to one with an address.
constexpr C * end() const noexcept
bool Derive(CExtKey &out, unsigned int nChild) const
std::unordered_map< uint32_t, CExtPubKey > ExtPubKeyMap
static bool IsSegwit(const Descriptor &desc)
Whether the descriptor represents, directly or not, a witness program.
CPubKey GetPubKey() const
Compute the public key from a private key.
TxoutType Solver(const CScript &scriptPubKey, std::vector< std::vector< unsigned char >> &vSolutionsRet)
Parse a scriptPubKey and identify script type for standard scripts.
CExtKey DecodeExtKey(const std::string &str)
#define CHECK_NONFATAL(condition)
Identity function.
constexpr bool IsTapscript(MiniscriptContext ms_ctx)
Whether the context Tapscript, ensuring the only other possibility is P2WSH.
bool IsHex(std::string_view str)
constexpr std::size_t size() const noexcept
Span< const char > Expr(Span< const char > &sp)
Extract the expression that sp begins with.
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.
static constexpr uint8_t TAPROOT_LEAF_TAPSCRIPT
virtual bool IsSolvable() const =0
Whether this descriptor has all information about signing ignoring lack of private keys...
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.
bool GetCachedParentExtPubKey(uint32_t key_exp_pos, CExtPubKey &xpub) const
Retrieve a cached parent xpub.
uint160 RIPEMD160(Span< const unsigned char > data)
Compute the 160-bit RIPEMD-160 hash of an array.
static const int MAX_PUBKEYS_PER_MULTISIG
CExtPubKey DecodeExtPubKey(const std::string &str)
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.
std::shared_ptr< const Node< Key > > NodeRef
std::unique_ptr< Descriptor > InferDescriptor(const CScript &script, const SigningProvider &provider)
Find a descriptor for the specified script, using information from provider where possible...
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 Func(const std::string &str, Span< const char > &sp)
Parse a function call.
constexpr unsigned char * begin()
bool GetKeyOriginByXOnly(const XOnlyPubKey &pubkey, KeyOriginInfo &info) const
std::vector< typename std::common_type< Args... >::type > Vector(Args &&... args)
Construct a vector with the specified elements.
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.
virtual bool GetTaprootSpendData(const XOnlyPubKey &output_key, TaprootSpendData &spenddata) const
bool ParseUInt32(std::string_view str, uint32_t *out)
Convert decimal string to unsigned 32-bit integer with strict parse error feedback.
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.
const unsigned char * begin() const
virtual bool GetPubKey(const CKeyID &address, CPubKey &pubkey) const
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a scriptPubKey for the destination.
virtual bool GetKeyOrigin(const CKeyID &keyid, KeyOriginInfo &info) const
const SigningProvider & DUMMY_SIGNING_PROVIDER
TaprootBuilder & Finalize(const XOnlyPubKey &internal_key)
Finalize the construction.
An encapsulated public key.
std::map< CKeyID, CPubKey > pubkeys
WitnessV1Taproot GetOutput()
Compute scriptPubKey (after Finalize()).
static OutputType GetOutputType(TxoutType type, bool is_from_p2sh)
virtual bool ToNormalizedString(const SigningProvider &provider, std::string &out, const DescriptorCache *cache=nullptr) const =0
Convert the descriptor to a normalized string.
static constexpr unsigned int MAX_PUBKEYS_PER_MULTI_A
The limit of keys in OP_CHECKSIGADD-based scripts.
bool Const(const std::string &str, Span< const char > &sp)
Parse a constant.
unsigned int size() const
Simple read-only vector-like interface.
bool IsCompressed() const
Check whether the public key corresponding to this private key is (to be) compressed.
std::string FormatHDKeypath(const std::vector< uint32_t > &path, bool apostrophe)
CPubKey GetEvenCorrespondingCPubKey() const
virtual std::optional< int64_t > MaxSatisfactionElems() const =0
Get the maximum size number of stack elements for satisfying this descriptor.
std::vector< T > Split(const Span< const char > &sp, std::string_view separators)
Split a string on any char found in separators, returning a vector.
virtual bool GetCScript(const CScriptID &scriptid, CScript &script) const
bool IsFullyValid() const
Determine if this pubkey is fully valid.
virtual bool GetKey(const CKeyID &address, CKey &key) const
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
Utility class to construct Taproot outputs from internal key and script tree.
void CacheLastHardenedExtPubKey(uint32_t key_exp_pos, const CExtPubKey &xpub)
Cache a last hardened xpub.
uint160 Hash160(const T1 &in1)
Compute the 160-bit hash an object.
bool operator<(const CNetAddr &a, const CNetAddr &b)
virtual std::optional< int64_t > ScriptSize() const =0
Get the size of the scriptPubKey for this descriptor.
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...
constexpr C * begin() const noexcept
std::vector< unsigned char > ToByteVector(const T &in)
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.
static constexpr size_t TAPROOT_CONTROL_MAX_NODE_COUNT
bool Derive(CExtPubKey &out, unsigned int nChild) const
std::string EncodeExtPubKey(const CExtPubKey &key)
static bool ValidDepths(const std::vector< int > &depths)
Check if a list of depths is legal (will lead to IsComplete()).
An interface to be implemented by keystores that support signing.
CExtPubKey Neuter() const
Cache for single descriptor's derived extended pubkeys.
Serialized script, used inside transaction inputs and outputs.
static bool GetPubKey(const SigningProvider &provider, const SignatureData &sigdata, const CKeyID &address, CPubKey &pubkey)
void CacheParentExtPubKey(uint32_t key_exp_pos, const CExtPubKey &xpub)
Cache a parent xpub.
std::variant< CNoDestination, PubKeyDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, PayToAnchor, WitnessUnknown > CTxDestination
A txout script categorized into standard templates.
TaprootBuilder & Add(int depth, Span< const unsigned char > script, int leaf_version, bool track=true)
Add a new script at a certain depth in the tree.
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE
A reference to a CKey: the Hash160 of its serialized public key.
DescriptorCache MergeAndDiff(const DescriptorCache &other)
Combine another DescriptorCache into this one.
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
uint256 DescriptorID(const Descriptor &desc)
Unique identifier that may not change over time, unless explicitly marked as not backwards compatible...
static std::vector< std::string > split(const std::string &str, const std::string &delims=" \)
A reference to a CScript: the Hash160 of its serialization.
std::string EncodeDestination(const CTxDestination &dest)
CScript GetScriptForRawPubKey(const CPubKey &pubKey)
Generate a P2PK script for the given pubkey.
bool IsComplete() const
Return whether there were either no leaves, or the leaves form a Huffman tree.
An encapsulated private key.
A Span is an object that can refer to a contiguous sequence of objects.
std::optional< std::pair< int, std::vector< Span< const unsigned char > > > > MatchMultiA(const CScript &script)
std::optional< OutputType > OutputTypeFromDestination(const CTxDestination &dest)
Get the OutputType for a CTxDestination.
CKey DecodeSecret(const std::string &str)
std::string GetDescriptorChecksum(const std::string &descriptor)
Get the checksum for a descriptor.
NodeRef< typename Ctx::Key > FromScript(const CScript &script, const Ctx &ctx)
virtual bool IsRange() const =0
Whether the expansion of this descriptor depends on the position.
virtual std::optional< OutputType > GetOutputType() const =0
std::unique_ptr< Descriptor > Parse(const std::string &descriptor, FlatSigningProvider &out, std::string &error, bool require_checksum)
Parse a descriptor string.
CTxDestination DecodeDestination(const std::string &str, std::string &error_msg, std::vector< int > *error_locations)
A hasher class for SHA-256.
CScript ParseScript(const std::string &s)
virtual std::string ToString(bool compat_format=false) const =0
Convert the descriptor back to a string, undoing parsing.
std::string EncodeSecret(const CKey &key)
std::vector< uint32_t > path
virtual bool ToPrivateString(const SigningProvider &provider, std::string &out) const =0
Convert the descriptor to a private string.
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 ...
void CacheDerivedExtPubKey(uint32_t key_exp_pos, uint32_t der_index, const CExtPubKey &xpub)
Cache an xpub derived at an index.
std::string EncodeExtKey(const CExtKey &key)
std::unordered_map< uint32_t, ExtPubKeyMap > m_derived_xpubs
Map key expression index -> map of (key derivation index -> xpub)
ExtPubKeyMap GetCachedLastHardenedExtPubKeys() const
Retrieve all cached last hardened xpubs.
std::string ToString(const T &t)
Locale-independent version of std::to_string.
Interface for parsed descriptor objects.
bool IsValid() const
Check whether this private key is valid.
bool GetCachedDerivedExtPubKey(uint32_t key_exp_pos, uint32_t der_index, CExtPubKey &xpub) const
Retrieve a cached xpub derived at an index.
bool IsCompressed() const
Check whether this is a compressed public key.