92uint64_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];
151std::string AddChecksum(
const std::string& str) {
return str +
"#" + DescriptorChecksum(str); }
157typedef std::vector<uint32_t> KeyPath;
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;
208 virtual bool ToPrivateString(
const SigningProvider& arg, std::string& out)
const = 0;
219 virtual std::optional<CPubKey> GetRootPubKey()
const = 0;
221 virtual std::optional<CExtPubKey> GetRootExtPubKey()
const = 0;
224class 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();
286class 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;
321 ret = ToString(StringType::PUBLIC);
326 return arg.
GetKey(m_pubkey.GetID(), key);
328 std::optional<CPubKey> GetRootPubKey()
const override
332 std::optional<CExtPubKey> GetRootExtPubKey()
const override
338enum class DeriveType {
345class 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
470 return ToString(type,
false);
472 bool ToPrivateString(
const SigningProvider& arg, std::string& out)
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) {
486 out = ToString(StringType::PUBLIC,
true);
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
605 bool IsSolvable()
const override
607 for (
const auto& arg : m_subdescriptor_args) {
608 if (!arg->IsSolvable())
return false;
614 bool IsRange() const final
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);
677 bool ToPrivateString(
const SigningProvider& arg, std::string& out)
const override
679 bool ret = ToStringHelper(&arg, out, StringType::PRIVATE);
680 out = AddChecksum(out);
686 bool ret = ToStringHelper(&arg, out, StringType::NORMALIZED, cache);
687 out = AddChecksum(out);
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 {}; }
757 std::optional<int64_t> MaxSatisfactionWeight(
bool)
const override {
return {}; }
759 std::optional<int64_t> MaxSatisfactionElems()
const override {
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);
777class 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; }
787 std::optional<OutputType> GetOutputType()
const override
791 bool IsSingleType() const final {
return true; }
792 bool ToPrivateString(
const SigningProvider& arg, std::string& out)
const final {
return false; }
798class RawDescriptor final :
public DescriptorImpl
802 std::string ToStringExtra()
const override {
return HexStr(m_script); }
806 bool IsSolvable() const final {
return false; }
808 std::optional<OutputType> GetOutputType()
const override
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(); }
821class 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; }
856class 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") {}
867 std::optional<OutputType> GetOutputType()
const override {
return OutputType::LEGACY; }
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; }
885class 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") {}
896 std::optional<OutputType> GetOutputType()
const override {
return OutputType::BECH32; }
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;
903 return (1 + sig_size + 1 + 33);
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; }
914class 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; }
938class 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; }
976class 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;
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(); }
1012class SHDescriptor final :
public DescriptorImpl
1018 if (
ret.size())
out.scripts.emplace(
CScriptID(scripts[0]), scripts[0]);
1022 bool IsSegwit()
const {
return m_subdescriptor_args[0]->GetOutputType() ==
OutputType::BECH32; }
1025 SHDescriptor(std::unique_ptr<DescriptorImpl> desc) : DescriptorImpl({}, std::move(desc),
"sh") {}
1027 std::optional<OutputType> GetOutputType()
const override
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;
1057class 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") {}
1068 std::optional<OutputType> GetOutputType()
const override {
return OutputType::BECH32; }
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;
1093class 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();
1226class 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();
1276class 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 {
1309enum class ParseScriptContext {
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));
1353std::unique_ptr<PubkeyProvider> ParsePubkeyInner(uint32_t key_exp_index,
const Span<const char>& sp, ParseScriptContext ctx,
FlatSigningProvider& out,
bool& apostrophe, std::string& error)
1355 bool permit_uncompressed = ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH;
1356 auto split = Split(sp,
'/');
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);
1407 DeriveType type = DeriveType::NO;
1408 if (split.back() ==
Span{
"*"}.
first(1)) {
1410 type = DeriveType::UNHARDENED;
1411 }
else if (split.back() ==
Span{
"*'"}.
first(2) || split.back() ==
Span{
"*h"}.
first(2)) {
1412 apostrophe = split.back() ==
Span{
"*'"}.
first(2);
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);
1463std::unique_ptr<PubkeyProvider> InferPubkey(
const CPubKey& pubkey, ParseScriptContext ctx,
const SigningProvider& provider)
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;
1481std::unique_ptr<PubkeyProvider> InferXOnlyPubkey(
const XOnlyPubKey& xkey, ParseScriptContext ctx,
const SigningProvider& 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;
2075 auto ret =
ParseScript(key_exp_index, sp, ParseScriptContext::TOP, out, error);
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);
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");
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.
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
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
A Span is an object that can refer to a contiguous sequence of objects.
constexpr std::size_t size() const noexcept
CONSTEXPR_IF_NOT_DEBUG Span< C > subspan(std::size_t offset) const noexcept
CONSTEXPR_IF_NOT_DEBUG Span< C > first(std::size_t count) const noexcept
constexpr C * begin() const noexcept
constexpr C * end() const noexcept
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.
static bool ValidDepths(const std::vector< int > &depths)
Check if a list of depths is legal (will lead to IsComplete()).
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.
TaprootBuilder & Finalize(const XOnlyPubKey &internal_key)
Finalize the construction.
const unsigned char * begin() const
CPubKey GetEvenCorrespondingCPubKey() const
bool IsFullyValid() const
Determine if this pubkey is fully valid.
constexpr unsigned char * begin()
void reserve(size_type new_capacity)
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(Span< const unsigned char > data)
Compute the 160-bit RIPEMD-160 hash of an array.
std::string HexStr(const 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.
std::shared_ptr< const Node< Key > > NodeRef
NodeRef< typename Ctx::Key > FromScript(const CScript &script, const Ctx &ctx)
bool Const(const std::string &str, Span< const char > &sp)
Parse a constant.
Span< const char > Expr(Span< const char > &sp)
Extract the expression that sp begins with.
bool Func(const std::string &str, Span< const char > &sp)
Parse a function call.
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.
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.
std::unique_ptr< Descriptor > Parse(const std::string &descriptor, FlatSigningProvider &out, std::string &error, bool require_checksum)
Parse a descriptor string.
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.
uint256 DescriptorID(const Descriptor &desc)
Unique identifier that may not change over time, unless explicitly marked as not backwards compatible...
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)
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.
std::optional< std::pair< int, std::vector< Span< const unsigned char > > > > MatchMultiA(const CScript &script)
CScript GetScriptForMultisig(int nRequired, const std::vector< CPubKey > &keys)
Generate a multisig 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.
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::string ToString(bool compat_format=false) const =0
Convert the descriptor back to a string, undoing parsing.
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.
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< typename std::common_type< Args... >::type > Vector(Args &&... args)
Construct a vector with the specified elements.