90 uint64_t
PolyMod(uint64_t c,
int val)
93 c = ((c & 0x7ffffffff) << 5) ^ val;
94 if (c0 & 1) c ^= 0xf5dee51989;
95 if (c0 & 2) c ^= 0xa9fdca3312;
96 if (c0 & 4) c ^= 0x1bab10e32d;
97 if (c0 & 8) c ^= 0x3706b1677a;
98 if (c0 & 16) c ^= 0x644d626ffd;
117 static std::string INPUT_CHARSET =
118 "0123456789()[],'/*abcdefgh@:$%{}" 119 "IJKLMNOPQRSTUVWXYZ&+-.;<=>?!^_|~" 120 "ijklmnopqrstuvwxyzABCDEFGH`#\"\\ ";
123 static std::string CHECKSUM_CHARSET =
"qpzry9x8gf2tvdw0s3jn54khce6mua7l";
128 for (
auto ch : span) {
129 auto pos = INPUT_CHARSET.find(ch);
130 if (pos == std::string::npos)
return "";
132 cls = cls * 3 + (pos >> 5);
133 if (++clscount == 3) {
140 if (clscount > 0) c =
PolyMod(c, cls);
141 for (
int j = 0; j < 8; ++j) c =
PolyMod(c, 0);
144 std::string
ret(8,
' ');
145 for (
int j = 0; j < 8; ++j) ret[j] = CHECKSUM_CHARSET[(c >> (5 * (7 - j))) & 31];
149 std::string AddChecksum(
const std::string& str) {
return str +
"#" + DescriptorChecksum(str); }
155 typedef std::vector<uint32_t> KeyPath;
158 struct PubkeyProvider
163 uint32_t m_expr_index;
166 explicit PubkeyProvider(uint32_t exp_index) : m_expr_index(exp_index) {}
168 virtual ~PubkeyProvider() =
default;
173 bool operator<(PubkeyProvider& other)
const {
179 other.GetPubKey(0, dummy, b, dummy_info);
192 virtual bool IsRange()
const = 0;
195 virtual size_t GetSize()
const = 0;
197 enum class StringType {
203 virtual std::string
ToString(StringType type=StringType::PUBLIC)
const = 0;
217 class OriginPubkeyProvider final :
public PubkeyProvider
220 std::unique_ptr<PubkeyProvider> m_provider;
223 std::string OriginString(StringType type,
bool normalized=
false)
const 226 bool use_apostrophe = (!normalized && m_apostrophe) || type == StringType::COMPAT;
231 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) {}
234 if (!m_provider->GetPubKey(pos, arg, key, info, read_cache, write_cache))
return false;
235 std::copy(std::begin(m_origin.fingerprint), std::end(m_origin.fingerprint), info.
fingerprint);
236 info.
path.insert(info.
path.begin(), m_origin.path.begin(), m_origin.path.end());
239 bool IsRange()
const override {
return m_provider->IsRange(); }
240 size_t GetSize()
const override {
return m_provider->GetSize(); }
241 std::string
ToString(StringType type)
const override {
return "[" + OriginString(type) +
"]" + m_provider->ToString(type); }
245 if (!m_provider->ToPrivateString(arg, sub))
return false;
246 ret =
"[" + OriginString(StringType::PUBLIC) +
"]" + std::move(sub);
252 if (!m_provider->ToNormalizedString(arg, sub, cache))
return false;
258 ret =
"[" + OriginString(StringType::PUBLIC,
true) + std::move(sub);
260 ret =
"[" + OriginString(StringType::PUBLIC,
true) +
"]" + std::move(sub);
266 return m_provider->GetPrivKey(pos, arg, key);
271 class ConstPubkeyProvider final :
public PubkeyProvider
277 ConstPubkeyProvider(uint32_t exp_index,
const CPubKey& pubkey,
bool xonly) : PubkeyProvider(exp_index), m_pubkey(pubkey), m_xonly(xonly) {}
282 CKeyID keyid = m_pubkey.GetID();
286 bool IsRange()
const override {
return false; }
287 size_t GetSize()
const override {
return m_pubkey.size(); }
288 std::string
ToString(StringType type)
const override {
return m_xonly ?
HexStr(m_pubkey).substr(2) :
HexStr(m_pubkey); }
293 for (
const auto& keyid :
XOnlyPubKey(m_pubkey).GetKeyIDs()) {
298 arg.
GetKey(m_pubkey.GetID(), key);
300 if (!key.
IsValid())
return false;
311 return arg.
GetKey(m_pubkey.GetID(), key);
322 class BIP32PubkeyProvider final :
public PubkeyProvider
334 if (!arg.
GetKey(m_root_extkey.pubkey.GetID(), key))
return false;
335 ret.nDepth = m_root_extkey.nDepth;
336 std::copy(m_root_extkey.vchFingerprint, m_root_extkey.vchFingerprint +
sizeof(
ret.vchFingerprint),
ret.vchFingerprint);
337 ret.nChild = m_root_extkey.nChild;
338 ret.chaincode = m_root_extkey.chaincode;
346 if (!GetExtKey(arg, xprv))
return false;
347 for (
auto entry : m_path) {
348 if (!xprv.
Derive(xprv, entry))
return false;
350 last_hardened = xprv;
356 bool IsHardened()
const 358 if (m_derive == DeriveType::HARDENED)
return true;
359 for (
auto entry : m_path) {
360 if (entry >> 31)
return true;
366 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) {}
367 bool IsRange()
const override {
return m_derive != DeriveType::NO; }
368 size_t GetSize()
const override {
return 33; }
373 CKeyID keyid = m_root_extkey.pubkey.GetID();
375 parent_info.
path = m_path;
379 if (m_derive == DeriveType::UNHARDENED) final_info_out_tmp.
path.push_back((uint32_t)pos);
380 if (m_derive == DeriveType::HARDENED) final_info_out_tmp.
path.push_back(((uint32_t)pos) | 0x80000000L);
388 if (!read_cache->GetCachedDerivedExtPubKey(m_expr_index, pos, final_extkey)) {
389 if (m_derive == DeriveType::HARDENED)
return false;
391 if (!read_cache->GetCachedParentExtPubKey(m_expr_index, parent_extkey))
return false;
392 final_extkey = parent_extkey;
393 if (m_derive == DeriveType::UNHARDENED) der = parent_extkey.
Derive(final_extkey, pos);
395 }
else if (IsHardened()) {
398 if (!GetDerivedExtKey(arg, xprv, lh_xprv))
return false;
399 parent_extkey = xprv.
Neuter();
400 if (m_derive == DeriveType::UNHARDENED) der = xprv.
Derive(xprv, pos);
401 if (m_derive == DeriveType::HARDENED) der = xprv.
Derive(xprv, pos | 0x80000000UL);
402 final_extkey = xprv.
Neuter();
404 last_hardened_extkey = lh_xprv.
Neuter();
407 for (
auto entry : m_path) {
408 if (!parent_extkey.
Derive(parent_extkey, entry))
return false;
410 final_extkey = parent_extkey;
411 if (m_derive == DeriveType::UNHARDENED) der = parent_extkey.
Derive(final_extkey, pos);
412 assert(m_derive != DeriveType::HARDENED);
414 if (!der)
return false;
416 final_info_out = final_info_out_tmp;
417 key_out = final_extkey.
pubkey;
421 if (m_derive != DeriveType::HARDENED) {
422 write_cache->CacheParentExtPubKey(m_expr_index, parent_extkey);
425 write_cache->CacheLastHardenedExtPubKey(m_expr_index, last_hardened_extkey);
427 }
else if (final_info_out.
path.size() > 0) {
428 write_cache->CacheDerivedExtPubKey(m_expr_index, pos, final_extkey);
434 std::string
ToString(StringType type,
bool normalized)
const 437 const bool use_apostrophe = (!normalized && m_apostrophe) || type == StringType::COMPAT;
441 if (m_derive == DeriveType::HARDENED)
ret += use_apostrophe ?
'\'' :
'h';
445 std::string
ToString(StringType type=StringType::PUBLIC)
const override 452 if (!GetExtKey(arg, key))
return false;
456 if (m_derive == DeriveType::HARDENED)
out += m_apostrophe ?
'\'' :
'h';
462 if (m_derive == DeriveType::HARDENED) {
468 int i = (int)m_path.size() - 1;
469 for (; i >= 0; --i) {
470 if (m_path.at(i) >> 31) {
482 for (;
k <= i; ++
k) {
484 origin.
path.push_back(m_path.at(
k));
488 for (;
k < (int)m_path.size(); ++
k) {
489 end_path.push_back(m_path.at(
k));
492 CKeyID id = m_root_extkey.pubkey.GetID();
493 std::copy(
id.begin(),
id.begin() + 4, origin.
fingerprint);
498 if (cache !=
nullptr) {
504 if (!GetDerivedExtKey(arg, xprv, lh_xprv))
return false;
514 assert(m_derive == DeriveType::UNHARDENED);
522 if (!GetDerivedExtKey(arg, extkey, dummy))
return false;
523 if (m_derive == DeriveType::UNHARDENED && !extkey.
Derive(extkey, pos))
return false;
524 if (m_derive == DeriveType::HARDENED && !extkey.
Derive(extkey, pos | 0x80000000UL))
return false;
535 const std::vector<std::unique_ptr<PubkeyProvider>> m_pubkey_args;
537 const std::string m_name;
543 const std::vector<std::unique_ptr<DescriptorImpl>> m_subdescriptor_args;
546 virtual std::string ToStringExtra()
const {
return ""; }
561 DescriptorImpl(std::vector<std::unique_ptr<PubkeyProvider>> pubkeys,
const std::string&
name) : m_pubkey_args(
std::move(pubkeys)), m_name(
name), m_subdescriptor_args() {}
562 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))) {}
563 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)) {}
565 enum class StringType
575 for (
const auto& arg : m_subdescriptor_args) {
576 if (!arg->IsSolvable())
return false;
583 for (
const auto& pubkey : m_pubkey_args) {
584 if (pubkey->IsRange())
return true;
586 for (
const auto& arg : m_subdescriptor_args) {
587 if (arg->IsRange())
return true;
595 for (
const auto& scriptarg : m_subdescriptor_args) {
596 if (pos++)
ret +=
",";
598 if (!scriptarg->ToStringHelper(arg, tmp, type, cache))
return false;
606 std::string extra = ToStringExtra();
607 size_t pos = extra.size() > 0 ? 1 : 0;
608 std::string
ret = m_name +
"(" + extra;
609 for (
const auto& pubkey : m_pubkey_args) {
610 if (pos++)
ret +=
",";
613 case StringType::NORMALIZED:
614 if (!pubkey->ToNormalizedString(*arg, tmp, cache))
return false;
616 case StringType::PRIVATE:
617 if (!pubkey->ToPrivateString(*arg, tmp))
return false;
619 case StringType::PUBLIC:
620 tmp = pubkey->ToString();
622 case StringType::COMPAT:
623 tmp = pubkey->ToString(PubkeyProvider::StringType::COMPAT);
628 std::string subscript;
629 if (!ToStringSubScriptHelper(arg, subscript, type, cache))
return false;
630 if (pos && subscript.size())
ret +=
',';
631 out = std::move(
ret) + std::move(subscript) +
")";
635 std::string
ToString(
bool compat_format)
const final 638 ToStringHelper(
nullptr,
ret, compat_format ? StringType::COMPAT : StringType::PUBLIC);
639 return AddChecksum(
ret);
644 bool ret = ToStringHelper(&arg,
out, StringType::PRIVATE);
651 bool ret = ToStringHelper(&arg,
out, StringType::NORMALIZED, cache);
658 std::vector<std::pair<CPubKey, KeyOriginInfo>> entries;
659 entries.reserve(m_pubkey_args.size());
662 for (
const auto& p : m_pubkey_args) {
663 entries.emplace_back();
664 if (!p->GetPubKey(pos, arg, entries.back().first, entries.back().second, read_cache, write_cache))
return false;
666 std::vector<CScript> subscripts;
668 for (
const auto& subarg : m_subdescriptor_args) {
669 std::vector<CScript> outscripts;
670 if (!subarg->ExpandHelper(pos, arg, read_cache, outscripts, subprovider, write_cache))
return false;
671 assert(outscripts.size() == 1);
672 subscripts.emplace_back(std::move(outscripts[0]));
674 out.Merge(std::move(subprovider));
676 std::vector<CPubKey> pubkeys;
677 pubkeys.reserve(entries.size());
678 for (
auto& entry : entries) {
679 pubkeys.push_back(entry.first);
680 out.origins.emplace(entry.first.GetID(), std::make_pair<CPubKey, KeyOriginInfo>(
CPubKey(entry.first), std::move(entry.second)));
683 output_scripts = MakeScripts(pubkeys,
Span{subscripts},
out);
689 return ExpandHelper(pos, provider,
nullptr, output_scripts,
out, write_cache);
699 for (
const auto& p : m_pubkey_args) {
701 if (!p->GetPrivKey(pos, provider, key))
continue;
704 for (
const auto& arg : m_subdescriptor_args) {
705 arg->ExpandPrivate(pos, provider,
out);
709 std::optional<OutputType>
GetOutputType()
const override {
return std::nullopt; }
711 std::optional<int64_t>
ScriptSize()
const override {
return {}; }
718 virtual std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const {
return {}; }
726 class AddressDescriptor final :
public DescriptorImpl
730 std::string ToStringExtra()
const override {
return EncodeDestination(m_destination); }
733 AddressDescriptor(
CTxDestination destination) : DescriptorImpl({},
"addr"), m_destination(std::move(destination)) {}
734 bool IsSolvable() const final {
return false; }
740 bool IsSingleType() const final {
return true; }
741 bool ToPrivateString(
const SigningProvider& arg, std::string&
out)
const final {
return false; }
747 class RawDescriptor final :
public DescriptorImpl
751 std::string ToStringExtra()
const override {
return HexStr(m_script); }
754 RawDescriptor(
CScript script) : DescriptorImpl({},
"raw"), m_script(std::move(script)) {}
755 bool IsSolvable() const final {
return false; }
763 bool IsSingleType() const final {
return true; }
764 bool ToPrivateString(
const SigningProvider& arg, std::string&
out)
const final {
return false; }
766 std::optional<int64_t> ScriptSize()
const override {
return m_script.size(); }
770 class PKDescriptor final :
public DescriptorImpl
779 return Vector(std::move(script));
785 PKDescriptor(std::unique_ptr<PubkeyProvider> prov,
bool xonly =
false) : DescriptorImpl(
Vector(
std::move(prov)),
"pk"), m_xonly(xonly) {}
786 bool IsSingleType() const final {
return true; }
788 std::optional<int64_t> ScriptSize()
const override {
789 return 1 + (m_xonly ? 32 : m_pubkey_args[0]->GetSize()) + 1;
792 std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const override {
793 const auto ecdsa_sig_size = use_max_sig ? 72 : 71;
794 return 1 + (m_xonly ? 65 : ecdsa_sig_size);
797 std::optional<int64_t> MaxSatisfactionWeight(
bool use_max_sig)
const override {
801 std::optional<int64_t> MaxSatisfactionElems()
const override {
return 1; }
805 class PKHDescriptor final :
public DescriptorImpl
810 CKeyID id = keys[0].GetID();
811 out.pubkeys.emplace(
id, keys[0]);
815 PKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(
Vector(
std::move(prov)),
"pkh") {}
817 bool IsSingleType() const final {
return true; }
819 std::optional<int64_t> ScriptSize()
const override {
return 1 + 1 + 1 + 20 + 1 + 1; }
821 std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const override {
822 const auto sig_size = use_max_sig ? 72 : 71;
823 return 1 +
sig_size + 1 + m_pubkey_args[0]->GetSize();
826 std::optional<int64_t> MaxSatisfactionWeight(
bool use_max_sig)
const override {
830 std::optional<int64_t> MaxSatisfactionElems()
const override {
return 2; }
834 class WPKHDescriptor final :
public DescriptorImpl
839 CKeyID id = keys[0].GetID();
840 out.pubkeys.emplace(
id, keys[0]);
844 WPKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(
Vector(
std::move(prov)),
"wpkh") {}
846 bool IsSingleType() const final {
return true; }
848 std::optional<int64_t> ScriptSize()
const override {
return 1 + 1 + 20; }
850 std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const override {
851 const auto sig_size = use_max_sig ? 72 : 71;
855 std::optional<int64_t> MaxSatisfactionWeight(
bool use_max_sig)
const override {
856 return MaxSatSize(use_max_sig);
859 std::optional<int64_t> MaxSatisfactionElems()
const override {
return 2; }
863 class ComboDescriptor final :
public DescriptorImpl
868 std::vector<CScript>
ret;
869 CKeyID id = keys[0].GetID();
870 out.pubkeys.emplace(
id, keys[0]);
873 if (keys[0].IsCompressed()) {
876 ret.emplace_back(p2wpkh);
882 ComboDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(
Vector(
std::move(prov)),
"combo") {}
883 bool IsSingleType() const final {
return false; }
887 class MultisigDescriptor final :
public DescriptorImpl
889 const int m_threshold;
892 std::string ToStringExtra()
const override {
return strprintf(
"%i", m_threshold); }
895 std::vector<CPubKey> sorted_keys(keys);
896 std::sort(sorted_keys.begin(), sorted_keys.end());
902 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) {}
903 bool IsSingleType() const final {
return true; }
905 std::optional<int64_t> ScriptSize()
const override {
906 const auto n_keys = m_pubkey_args.size();
907 auto op = [](int64_t acc,
const std::unique_ptr<PubkeyProvider>&
pk) {
return acc + 1 +
pk->GetSize();};
908 const auto pubkeys_size{std::accumulate(m_pubkey_args.begin(), m_pubkey_args.end(), int64_t{0}, op)};
912 std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const override {
913 const auto sig_size = use_max_sig ? 72 : 71;
914 return (1 + (1 +
sig_size) * m_threshold);
917 std::optional<int64_t> MaxSatisfactionWeight(
bool use_max_sig)
const override {
921 std::optional<int64_t> MaxSatisfactionElems()
const override {
return 1 + m_threshold; }
925 class MultiADescriptor final :
public DescriptorImpl
927 const int m_threshold;
930 std::string ToStringExtra()
const override {
return strprintf(
"%i", m_threshold); }
933 std::vector<XOnlyPubKey> xkeys;
934 xkeys.reserve(keys.size());
935 for (
const auto& key : keys) xkeys.emplace_back(key);
936 if (m_sorted) std::sort(xkeys.begin(), xkeys.end());
938 for (
size_t i = 1; i < keys.size(); ++i) {
945 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) {}
946 bool IsSingleType() const final {
return true; }
948 std::optional<int64_t> ScriptSize()
const override {
949 const auto n_keys = m_pubkey_args.size();
953 std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const override {
954 return (1 + 65) * m_threshold + (m_pubkey_args.size() - m_threshold);
957 std::optional<int64_t> MaxSatisfactionElems()
const override {
return m_pubkey_args.size(); }
961 class SHDescriptor final :
public DescriptorImpl
967 if (
ret.size())
out.scripts.emplace(
CScriptID(scripts[0]), scripts[0]);
974 SHDescriptor(std::unique_ptr<DescriptorImpl> desc) : DescriptorImpl({}, std::move(desc),
"sh") {}
978 assert(m_subdescriptor_args.size() == 1);
982 bool IsSingleType() const final {
return true; }
984 std::optional<int64_t> ScriptSize()
const override {
return 1 + 1 + 20 + 1; }
986 std::optional<int64_t> MaxSatisfactionWeight(
bool use_max_sig)
const override {
987 if (
const auto sat_size = m_subdescriptor_args[0]->MaxSatSize(use_max_sig)) {
988 if (
const auto subscript_size = m_subdescriptor_args[0]->ScriptSize()) {
992 if (
IsSegwit())
return subscript_weight + *sat_size;
999 std::optional<int64_t> MaxSatisfactionElems()
const override {
1000 if (
const auto sub_elems = m_subdescriptor_args[0]->MaxSatisfactionElems())
return 1 + *sub_elems;
1006 class WSHDescriptor final :
public DescriptorImpl
1012 if (
ret.size())
out.scripts.emplace(
CScriptID(scripts[0]), scripts[0]);
1016 WSHDescriptor(std::unique_ptr<DescriptorImpl> desc) : DescriptorImpl({}, std::move(desc),
"wsh") {}
1018 bool IsSingleType() const final {
return true; }
1020 std::optional<int64_t> ScriptSize()
const override {
return 1 + 1 + 32; }
1022 std::optional<int64_t> MaxSatSize(
bool use_max_sig)
const override {
1023 if (
const auto sat_size = m_subdescriptor_args[0]->MaxSatSize(use_max_sig)) {
1024 if (
const auto subscript_size = m_subdescriptor_args[0]->ScriptSize()) {
1031 std::optional<int64_t> MaxSatisfactionWeight(
bool use_max_sig)
const override {
1032 return MaxSatSize(use_max_sig);
1035 std::optional<int64_t> MaxSatisfactionElems()
const override {
1036 if (
const auto sub_elems = m_subdescriptor_args[0]->MaxSatisfactionElems())
return 1 + *sub_elems;
1042 class TRDescriptor final :
public DescriptorImpl
1044 std::vector<int> m_depths;
1050 for (
size_t pos = 0; pos < m_depths.size(); ++pos) {
1054 assert(keys.size() == 1);
1056 if (!xpk.IsFullyValid())
return {};
1059 out.tr_trees[output] = builder;
1060 out.pubkeys.emplace(keys[0].GetID(), keys[0]);
1065 if (m_depths.empty())
return true;
1066 std::vector<bool> path;
1067 for (
size_t pos = 0; pos < m_depths.size(); ++pos) {
1068 if (pos)
ret +=
',';
1069 while ((
int)path.size() <= m_depths[pos]) {
1070 if (path.size())
ret +=
'{';
1071 path.push_back(
false);
1074 if (!m_subdescriptor_args[pos]->ToStringHelper(arg, tmp, type, cache))
return false;
1076 while (!path.empty() && path.back()) {
1077 if (path.size() > 1)
ret +=
'}';
1080 if (!path.empty()) path.back() =
true;
1085 TRDescriptor(std::unique_ptr<PubkeyProvider> internal_key, std::vector<std::unique_ptr<DescriptorImpl>> descs, std::vector<int> depths) :
1086 DescriptorImpl(
Vector(
std::move(internal_key)),
std::move(descs),
"tr"), m_depths(
std::move(depths))
1088 assert(m_subdescriptor_args.size() == m_depths.size());
1091 bool IsSingleType() const final {
return true; }
1093 std::optional<int64_t> ScriptSize()
const override {
return 1 + 1 + 32; }
1095 std::optional<int64_t> MaxSatisfactionWeight(
bool)
const override {
1100 std::optional<int64_t> MaxSatisfactionElems()
const override {
1116 const std::vector<CPubKey>& m_keys;
1123 uint160 GetHash160(uint32_t key)
const {
1127 return m_keys[key].GetID();
1133 std::vector<unsigned char> ToPKBytes(uint32_t key)
const {
1136 return {m_keys[key].begin(), m_keys[key].end()};
1139 return {xonly_pubkey.
begin(), xonly_pubkey.end()};
1142 std::vector<unsigned char> ToPKHBytes(uint32_t key)
const {
1143 auto id = GetHash160(key);
1144 return {
id.begin(),
id.end()};
1155 const std::vector<std::unique_ptr<PubkeyProvider>>& m_pubkeys;
1161 : m_arg(arg), m_pubkeys(pubkeys), m_private(priv) {}
1163 std::optional<std::string>
ToString(uint32_t key)
const 1167 if (!m_pubkeys[key]->ToPrivateString(*m_arg,
ret))
return {};
1169 ret = m_pubkeys[key]->ToString();
1175 class MiniscriptDescriptor final :
public DescriptorImpl
1181 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>& keys,
Span<const CScript> scripts,
1184 const auto script_ctx{
m_node->GetMsCtx()};
1185 for (
const auto& key : keys) {
1189 provider.
pubkeys.emplace(key.GetID(), key);
1192 return Vector(
m_node->ToScript(ScriptMaker(keys, script_ctx)));
1199 bool ToStringHelper(
const SigningProvider* arg, std::string&
out,
const StringType type,
1202 if (
const auto res =
m_node->ToString(StringMaker(arg, m_pubkey_args, type == StringType::PRIVATE))) {
1209 bool IsSolvable()
const override {
return true; }
1210 bool IsSingleType() const final {
return true; }
1212 std::optional<int64_t> ScriptSize()
const override {
return m_node->ScriptSize(); }
1214 std::optional<int64_t> MaxSatSize(
bool)
const override {
1216 return m_node->GetWitnessSize();
1219 std::optional<int64_t> MaxSatisfactionElems()
const override {
1220 return m_node->GetStackSize();
1225 class RawTRDescriptor final :
public DescriptorImpl
1230 assert(keys.size() == 1);
1232 if (!xpk.IsFullyValid())
return {};
1237 RawTRDescriptor(std::unique_ptr<PubkeyProvider> output_key) : DescriptorImpl(
Vector(
std::move(output_key)),
"rawtr") {}
1239 bool IsSingleType() const final {
return true; }
1241 std::optional<int64_t> ScriptSize()
const override {
return 1 + 1 + 32; }
1243 std::optional<int64_t> MaxSatisfactionWeight(
bool)
const override {
1248 std::optional<int64_t> MaxSatisfactionElems()
const override {
1275 [[nodiscard]]
bool ParseKeyPath(
const std::vector<
Span<const char>>& split, KeyPath&
out,
bool& apostrophe, std::string&
error)
1277 for (
size_t i = 1; i < split.size(); ++i) {
1279 bool hardened =
false;
1280 if (elem.
size() > 0) {
1281 const char last = elem[elem.
size() - 1];
1282 if (last ==
'\'' || last ==
'h') {
1285 apostrophe = last ==
'\'';
1292 }
else if (p > 0x7FFFFFFFUL) {
1296 out.push_back(p | (((uint32_t)hardened) << 31));
1306 bool permit_uncompressed = ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH;
1307 auto split =
Split(sp,
'/');
1308 std::string str(split[0].begin(), split[0].end());
1309 if (str.size() == 0) {
1310 error =
"No key provided";
1313 if (split.size() == 1) {
1315 std::vector<unsigned char> data =
ParseHex(str);
1317 if (pubkey.IsValid() && !pubkey.IsValidNonHybrid()) {
1318 error =
"Hybrid public keys are not allowed";
1321 if (pubkey.IsFullyValid()) {
1322 if (permit_uncompressed || pubkey.IsCompressed()) {
1323 return std::make_unique<ConstPubkeyProvider>(key_exp_index, pubkey,
false);
1325 error =
"Uncompressed keys are not allowed";
1328 }
else if (data.size() == 32 && ctx == ParseScriptContext::P2TR) {
1329 unsigned char fullkey[33] = {0x02};
1330 std::copy(data.begin(), data.end(), fullkey + 1);
1331 pubkey.Set(std::begin(fullkey), std::end(fullkey));
1332 if (pubkey.IsFullyValid()) {
1333 return std::make_unique<ConstPubkeyProvider>(key_exp_index, pubkey,
true);
1343 out.keys.emplace(pubkey.
GetID(), key);
1344 return std::make_unique<ConstPubkeyProvider>(key_exp_index, pubkey, ctx == ParseScriptContext::P2TR);
1346 error =
"Uncompressed keys are not allowed";
1359 if (split.back() ==
Span{
"*"}.
first(1)) {
1361 type = DeriveType::UNHARDENED;
1362 }
else if (split.back() ==
Span{
"*'"}.
first(2) || split.back() ==
Span{
"*h"}.
first(2)) {
1363 apostrophe = split.back() ==
Span{
"*'"}.
first(2);
1365 type = DeriveType::HARDENED;
1367 if (!ParseKeyPath(split, path, apostrophe,
error))
return nullptr;
1369 extpubkey = extkey.
Neuter();
1372 return std::make_unique<BIP32PubkeyProvider>(key_exp_index, extpubkey, std::move(path), type, apostrophe);
1380 auto origin_split =
Split(sp,
']');
1381 if (origin_split.size() > 2) {
1382 error =
"Multiple ']' characters found for a single pubkey";
1386 bool apostrophe =
false;
1387 if (origin_split.size() == 1) {
1388 return ParsePubkeyInner(key_exp_index, origin_split[0], ctx,
out, apostrophe,
error);
1390 if (origin_split[0].empty() || origin_split[0][0] !=
'[') {
1391 error =
strprintf(
"Key origin start '[ character expected but not found, got '%c' instead",
1392 origin_split[0].empty() ?
']' : origin_split[0][0]);
1395 auto slash_split =
Split(origin_split[0].subspan(1),
'/');
1396 if (slash_split[0].size() != 8) {
1397 error =
strprintf(
"Fingerprint is not 4 bytes (%u characters instead of 8 characters)", slash_split[0].size());
1400 std::string fpr_hex = std::string(slash_split[0].begin(), slash_split[0].end());
1401 if (!
IsHex(fpr_hex)) {
1405 auto fpr_bytes =
ParseHex(fpr_hex);
1407 static_assert(
sizeof(info.
fingerprint) == 4,
"Fingerprint must be 4 bytes");
1408 assert(fpr_bytes.size() == 4);
1409 std::copy(fpr_bytes.begin(), fpr_bytes.end(), info.
fingerprint);
1410 if (!ParseKeyPath(slash_split, info.
path, apostrophe,
error))
return nullptr;
1411 auto provider = ParsePubkeyInner(key_exp_index, origin_split[1], ctx,
out, apostrophe,
error);
1412 if (!provider)
return nullptr;
1413 return std::make_unique<OriginPubkeyProvider>(key_exp_index, std::move(info), std::move(provider), apostrophe);
1423 if (ctx != ParseScriptContext::TOP && ctx != ParseScriptContext::P2SH && !pubkey.
IsCompressed()) {
1426 std::unique_ptr<PubkeyProvider> key_provider = std::make_unique<ConstPubkeyProvider>(0, pubkey,
false);
1429 return std::make_unique<OriginPubkeyProvider>(0, std::move(info), std::move(key_provider),
false);
1431 return key_provider;
1437 std::unique_ptr<PubkeyProvider> key_provider = std::make_unique<ConstPubkeyProvider>(0, pubkey,
true);
1440 return std::make_unique<OriginPubkeyProvider>(0, std::move(info), std::move(key_provider),
false);
1442 return key_provider;
1450 using Key = uint32_t;
1456 mutable std::vector<std::unique_ptr<PubkeyProvider>> m_keys;
1458 mutable std::string m_key_parsing_error;
1466 : m_out(
out), m_in(in), m_script_ctx(ctx), m_offset(offset) {}
1468 bool KeyCompare(
const Key& a,
const Key& b)
const {
1469 return *m_keys.at(a) < *m_keys.at(b);
1473 switch (m_script_ctx) {
1480 template<
typename I> std::optional<Key>
FromString(I begin, I end)
const 1483 Key key = m_keys.
size();
1484 auto pk = ParsePubkey(m_offset + key, {&*begin, &*end},
ParseContext(), *m_out, m_key_parsing_error);
1486 m_keys.push_back(std::move(
pk));
1490 std::optional<std::string>
ToString(
const Key& key)
const 1492 return m_keys.at(key)->ToString();
1495 template<
typename I> std::optional<Key> FromPKBytes(I begin, I end)
const 1498 Key key = m_keys.size();
1501 std::copy(begin, end, pubkey.
begin());
1503 m_keys.push_back(std::move(pubkey_provider));
1508 if (
auto pubkey_provider = InferPubkey(pubkey,
ParseContext(), *m_in)) {
1509 m_keys.push_back(std::move(pubkey_provider));
1516 template<
typename I> std::optional<Key> FromPKHBytes(I begin, I end)
const 1518 assert(end - begin == 20);
1521 std::copy(begin, end, hash.
begin());
1525 if (
auto pubkey_provider = InferPubkey(pubkey,
ParseContext(), *m_in)) {
1526 Key key = m_keys.
size();
1527 m_keys.push_back(std::move(pubkey_provider));
1535 return m_script_ctx;
1544 auto expr =
Expr(sp);
1545 if (
Func(
"pk", expr)) {
1546 auto pubkey = ParsePubkey(key_exp_index, expr, ctx,
out,
error);
1552 return std::make_unique<PKDescriptor>(std::move(pubkey), ctx == ParseScriptContext::P2TR);
1554 if ((ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH) &&
Func(
"pkh", expr)) {
1555 auto pubkey = ParsePubkey(key_exp_index, expr, ctx,
out,
error);
1561 return std::make_unique<PKHDescriptor>(std::move(pubkey));
1562 }
else if (ctx != ParseScriptContext::P2TR &&
Func(
"pkh", expr)) {
1564 error =
"Can only have pkh at top level, in sh(), wsh(), or in tr()";
1567 if (ctx == ParseScriptContext::TOP &&
Func(
"combo", expr)) {
1568 auto pubkey = ParsePubkey(key_exp_index, expr, ctx,
out,
error);
1574 return std::make_unique<ComboDescriptor>(std::move(pubkey));
1575 }
else if (
Func(
"combo", expr)) {
1576 error =
"Can only have combo() at top level";
1579 const bool multi =
Func(
"multi", expr);
1580 const bool sortedmulti = !multi &&
Func(
"sortedmulti", expr);
1581 const bool multi_a = !(multi || sortedmulti) &&
Func(
"multi_a", expr);
1582 const bool sortedmulti_a = !(multi || sortedmulti || multi_a) &&
Func(
"sortedmulti_a", expr);
1583 if (((ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH) && (multi || sortedmulti)) ||
1584 (ctx == ParseScriptContext::P2TR && (multi_a || sortedmulti_a))) {
1585 auto threshold =
Expr(expr);
1587 std::vector<std::unique_ptr<PubkeyProvider>> providers;
1588 if (!
ParseUInt32(std::string(threshold.begin(), threshold.end()), &thres)) {
1589 error =
strprintf(
"Multi threshold '%s' is not valid", std::string(threshold.begin(), threshold.end()));
1592 size_t script_size = 0;
1593 while (expr.size()) {
1594 if (!
Const(
",", expr)) {
1598 auto arg =
Expr(expr);
1599 auto pk = ParsePubkey(key_exp_index, arg, ctx,
out,
error);
1604 script_size +=
pk->GetSize() + 1;
1605 providers.emplace_back(std::move(
pk));
1614 }
else if (thres < 1) {
1615 error =
strprintf(
"Multisig threshold cannot be %d, must be at least 1", thres);
1617 }
else if (thres > providers.size()) {
1618 error =
strprintf(
"Multisig threshold cannot be larger than the number of keys; threshold is %d but only %u keys specified", thres, providers.size());
1621 if (ctx == ParseScriptContext::TOP) {
1622 if (providers.size() > 3) {
1623 error =
strprintf(
"Cannot have %u pubkeys in bare multisig; only at most 3 pubkeys", providers.size());
1627 if (ctx == ParseScriptContext::P2SH) {
1634 if (multi || sortedmulti) {
1635 return std::make_unique<MultisigDescriptor>(thres, std::move(providers), sortedmulti);
1637 return std::make_unique<MultiADescriptor>(thres, std::move(providers), sortedmulti_a);
1639 }
else if (multi || sortedmulti) {
1640 error =
"Can only have multi/sortedmulti at top level, in sh(), or in wsh()";
1642 }
else if (multi_a || sortedmulti_a) {
1643 error =
"Can only have multi_a/sortedmulti_a inside tr()";
1646 if ((ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH) &&
Func(
"wpkh", expr)) {
1647 auto pubkey = ParsePubkey(key_exp_index, expr, ParseScriptContext::P2WPKH,
out,
error);
1653 return std::make_unique<WPKHDescriptor>(std::move(pubkey));
1654 }
else if (
Func(
"wpkh", expr)) {
1655 error =
"Can only have wpkh() at top level or inside sh()";
1658 if (ctx == ParseScriptContext::TOP &&
Func(
"sh", expr)) {
1660 if (!desc || expr.size())
return nullptr;
1661 return std::make_unique<SHDescriptor>(std::move(desc));
1662 }
else if (
Func(
"sh", expr)) {
1663 error =
"Can only have sh() at top level";
1666 if ((ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH) &&
Func(
"wsh", expr)) {
1668 if (!desc || expr.size())
return nullptr;
1669 return std::make_unique<WSHDescriptor>(std::move(desc));
1670 }
else if (
Func(
"wsh", expr)) {
1671 error =
"Can only have wsh() at top level or inside sh()";
1674 if (ctx == ParseScriptContext::TOP &&
Func(
"addr", expr)) {
1677 error =
"Address is not valid";
1680 return std::make_unique<AddressDescriptor>(std::move(dest));
1681 }
else if (
Func(
"addr", expr)) {
1682 error =
"Can only have addr() at top level";
1685 if (ctx == ParseScriptContext::TOP &&
Func(
"tr", expr)) {
1686 auto arg =
Expr(expr);
1687 auto internal_key = ParsePubkey(key_exp_index, arg, ParseScriptContext::P2TR,
out,
error);
1688 if (!internal_key) {
1693 std::vector<std::unique_ptr<DescriptorImpl>> subscripts;
1694 std::vector<int> depths;
1696 if (!
Const(
",", expr)) {
1703 std::vector<bool> branches;
1708 while (
Const(
"{", expr)) {
1709 branches.push_back(
false);
1716 auto sarg =
Expr(expr);
1717 subscripts.emplace_back(
ParseScript(key_exp_index, sarg, ParseScriptContext::P2TR,
out,
error));
1718 if (!subscripts.back())
return nullptr;
1719 depths.push_back(branches.size());
1721 while (branches.size() && branches.back()) {
1722 if (!
Const(
"}", expr)) {
1726 branches.pop_back();
1729 if (branches.size() && !branches.back()) {
1730 if (!
Const(
",", expr)) {
1734 branches.back() =
true;
1736 }
while (branches.size());
1744 return std::make_unique<TRDescriptor>(std::move(internal_key), std::move(subscripts), std::move(depths));
1745 }
else if (
Func(
"tr", expr)) {
1746 error =
"Can only have tr at top level";
1749 if (ctx == ParseScriptContext::TOP &&
Func(
"rawtr", expr)) {
1750 auto arg =
Expr(expr);
1755 auto output_key = ParsePubkey(key_exp_index, arg, ParseScriptContext::P2TR,
out,
error);
1756 if (!output_key)
return nullptr;
1758 return std::make_unique<RawTRDescriptor>(std::move(output_key));
1759 }
else if (
Func(
"rawtr", expr)) {
1760 error =
"Can only have rawtr at top level";
1763 if (ctx == ParseScriptContext::TOP &&
Func(
"raw", expr)) {
1764 std::string str(expr.begin(), expr.end());
1766 error =
"Raw script is not hex";
1770 return std::make_unique<RawDescriptor>(
CScript(bytes.begin(), bytes.end()));
1771 }
else if (
Func(
"raw", expr)) {
1772 error =
"Can only have raw() at top level";
1778 KeyParser parser(&
out,
nullptr, script_ctx, key_exp_index);
1781 if (ctx != ParseScriptContext::P2WSH && ctx != ParseScriptContext::P2TR) {
1782 error =
"Miniscript expressions can only be used in wsh or tr.";
1785 if (parser.m_key_parsing_error !=
"") {
1786 error = std::move(parser.m_key_parsing_error);
1789 if (!
node->IsSane() ||
node->IsNotSatisfiable()) {
1791 auto insane_node =
node.get();
1792 if (
const auto sub =
node->FindInsaneSub()) insane_node = sub;
1793 if (
const auto str = insane_node->ToString(parser))
error = *str;
1794 if (!insane_node->IsValid()) {
1795 error +=
" is invalid";
1796 }
else if (!
node->IsSane()) {
1797 error +=
" is not sane";
1798 if (!insane_node->IsNonMalleable()) {
1799 error +=
": malleable witnesses exist";
1800 }
else if (insane_node ==
node.get() && !insane_node->NeedsSignature()) {
1801 error +=
": witnesses without signature exist";
1802 }
else if (!insane_node->CheckTimeLocksMix()) {
1803 error +=
": contains mixes of timelocks expressed in blocks and seconds";
1804 }
else if (!insane_node->CheckDuplicateKey()) {
1805 error +=
": contains duplicate public keys";
1806 }
else if (!insane_node->ValidSatisfactions()) {
1807 error +=
": needs witnesses that may exceed resource limits";
1810 error +=
" is not satisfiable";
1817 key_exp_index += parser.m_keys.size();
1818 return std::make_unique<MiniscriptDescriptor>(std::move(parser.m_keys), std::move(
node));
1821 if (ctx == ParseScriptContext::P2SH) {
1822 error =
"A function is needed within P2SH";
1824 }
else if (ctx == ParseScriptContext::P2WSH) {
1825 error =
"A function is needed within P2WSH";
1828 error =
strprintf(
"'%s' is not a valid descriptor function", std::string(expr.begin(), expr.end()));
1835 if (!match)
return {};
1836 std::vector<std::unique_ptr<PubkeyProvider>> keys;
1837 keys.reserve(match->second.size());
1838 for (
const auto keyspan : match->second) {
1839 if (keyspan.size() != 32)
return {};
1840 auto key = InferXOnlyPubkey(
XOnlyPubKey{keyspan}, ctx, provider);
1841 if (!key)
return {};
1842 keys.push_back(std::move(key));
1844 return std::make_unique<MultiADescriptor>(match->first, std::move(keys));
1849 if (ctx == ParseScriptContext::P2TR && script.
size() == 34 && script[0] == 32 && script[33] ==
OP_CHECKSIG) {
1851 return std::make_unique<PKDescriptor>(InferXOnlyPubkey(key, ctx, provider),
true);
1854 if (ctx == ParseScriptContext::P2TR) {
1855 auto ret = InferMultiA(script, ctx, provider);
1859 std::vector<std::vector<unsigned char>> data;
1862 if (txntype ==
TxoutType::PUBKEY && (ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH)) {
1864 if (
auto pubkey_provider = InferPubkey(pubkey, ctx, provider)) {
1865 return std::make_unique<PKDescriptor>(std::move(pubkey_provider));
1868 if (txntype ==
TxoutType::PUBKEYHASH && (ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH)) {
1872 if (provider.
GetPubKey(keyid, pubkey)) {
1873 if (
auto pubkey_provider = InferPubkey(pubkey, ctx, provider)) {
1874 return std::make_unique<PKHDescriptor>(std::move(pubkey_provider));
1882 if (provider.
GetPubKey(keyid, pubkey)) {
1883 if (
auto pubkey_provider = InferPubkey(pubkey, ParseScriptContext::P2WPKH, provider)) {
1884 return std::make_unique<WPKHDescriptor>(std::move(pubkey_provider));
1888 if (txntype ==
TxoutType::MULTISIG && (ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH)) {
1890 std::vector<std::unique_ptr<PubkeyProvider>> providers;
1891 for (
size_t i = 1; i + 1 < data.size(); ++i) {
1893 if (
auto pubkey_provider = InferPubkey(pubkey, ctx, provider)) {
1894 providers.push_back(std::move(pubkey_provider));
1900 if (ok)
return std::make_unique<MultisigDescriptor>((int)data[0][0], std::move(providers));
1906 if (provider.
GetCScript(scriptid, subscript)) {
1907 auto sub = InferScript(subscript, ParseScriptContext::P2SH, provider);
1908 if (sub)
return std::make_unique<SHDescriptor>(std::move(sub));
1914 if (provider.
GetCScript(scriptid, subscript)) {
1915 auto sub = InferScript(subscript, ParseScriptContext::P2WSH, provider);
1916 if (sub)
return std::make_unique<WSHDescriptor>(std::move(sub));
1922 std::copy(data[0].begin(), data[0].end(), pubkey.
begin());
1931 std::vector<std::unique_ptr<DescriptorImpl>> subscripts;
1932 std::vector<int> depths;
1933 for (
const auto& [depth, script, leaf_ver] : *tree) {
1934 std::unique_ptr<DescriptorImpl> subdesc;
1936 subdesc = InferScript(
CScript(script.
begin(), script.
end()), ParseScriptContext::P2TR, provider);
1942 subscripts.push_back(std::move(subdesc));
1943 depths.push_back(depth);
1947 auto key = InferXOnlyPubkey(tap.internal_key, ParseScriptContext::P2TR, provider);
1948 return std::make_unique<TRDescriptor>(std::move(key), std::move(subscripts), std::move(depths));
1954 auto key = InferXOnlyPubkey(pubkey, ParseScriptContext::P2TR, provider);
1956 return std::make_unique<RawTRDescriptor>(std::move(key));
1961 if (ctx == ParseScriptContext::P2WSH || ctx == ParseScriptContext::P2TR) {
1963 KeyParser parser(
nullptr, &provider, script_ctx);
1966 return std::make_unique<MiniscriptDescriptor>(std::move(parser.m_keys), std::move(
node));
1972 if (ctx != ParseScriptContext::TOP)
return nullptr;
1977 return std::make_unique<AddressDescriptor>(std::move(dest));
1981 return std::make_unique<RawDescriptor>(script);
1992 auto check_split =
Split(sp,
'#');
1993 if (check_split.size() > 2) {
1994 error =
"Multiple '#' symbols";
1997 if (check_split.size() == 1 && require_checksum){
1998 error =
"Missing checksum";
2001 if (check_split.size() == 2) {
2002 if (check_split[1].size() != 8) {
2003 error =
strprintf(
"Expected 8 character checksum, not %u characters", check_split[1].size());
2007 auto checksum = DescriptorChecksum(check_split[0]);
2008 if (checksum.empty()) {
2009 error =
"Invalid characters in payload";
2012 if (check_split.size() == 2) {
2013 if (!std::equal(checksum.begin(), checksum.end(), check_split[1].begin())) {
2014 error =
strprintf(
"Provided checksum '%s' does not match computed checksum '%s'", std::string(check_split[1].begin(), check_split[1].end()), checksum);
2018 if (out_checksum) *out_checksum = std::move(checksum);
2019 sp = check_split[0];
2027 uint32_t key_exp_index = 0;
2029 if (sp.
size() == 0 &&
ret)
return std::unique_ptr<Descriptor>(std::move(
ret));
2044 return InferScript(script, ParseScriptContext::TOP, provider);
2049 std::string desc_str = desc.
ToString(
true);
2051 CSHA256().
Write((
unsigned char*)desc_str.data(), desc_str.size()).Finalize(
id.begin());
2063 xpubs[der_index] = xpub;
2083 const auto& der_it = key_exp_it->second.find(der_index);
2084 if (der_it == key_exp_it->second.end())
return false;
2085 xpub = der_it->second;
2103 if (xpub != parent_xpub_pair.second) {
2104 throw std::runtime_error(std::string(__func__) +
": New cached parent xpub does not match already cached parent xpub");
2112 for (
const auto& derived_xpub_pair : derived_xpub_map_pair.second) {
2115 if (xpub != derived_xpub_pair.second) {
2116 throw std::runtime_error(std::string(__func__) +
": New cached derived xpub does not match already cached derived xpub");
2120 CacheDerivedExtPubKey(derived_xpub_map_pair.first, derived_xpub_pair.first, derived_xpub_pair.second);
2121 diff.
CacheDerivedExtPubKey(derived_xpub_map_pair.first, derived_xpub_pair.first, derived_xpub_pair.second);
2127 if (xpub != lh_xpub_pair.second) {
2128 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)
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.
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.
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
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 Func(const std::string &str, Span< const char > &sp)
Parse a function call.
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
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)
std::string GetDescriptorChecksum(const std::string &descriptor)
Get the checksum for a descriptor.
bool Const(const std::string &str, Span< const char > &sp)
Parse a constant.
#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
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
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.
Span< const char > Expr(Span< const char > &sp)
Extract the expression that sp begins with.
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
std::unique_ptr< Descriptor > Parse(const std::string &descriptor, FlatSigningProvider &out, std::string &error, bool require_checksum)
Parse a descriptor string.
std::string ToString(const T &t)
Locale-independent version of std::to_string.
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.
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
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.
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.
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.
std::variant< CNoDestination, PubKeyDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, WitnessUnknown > CTxDestination
A txout script categorized into standard templates.
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()).
std::unique_ptr< Descriptor > InferDescriptor(const CScript &script, const SigningProvider &provider)
Find a descriptor for the specified script, using information from provider where possible...
An interface to be implemented by keystores that support signing.
CExtPubKey Neuter() const
std::unordered_map< uint32_t, CExtPubKey > ExtPubKeyMap
bool error(const char *fmt, const Args &... args)
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.
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.
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)
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
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 –...
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)
uint256 DescriptorID(const Descriptor &desc)
Unique identifier that may not change over time, unless explicitly marked as not backwards compatible...
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.
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.