87 uint64_t
PolyMod(uint64_t c,
int val)
90 c = ((c & 0x7ffffffff) << 5) ^ val;
91 if (c0 & 1) c ^= 0xf5dee51989;
92 if (c0 & 2) c ^= 0xa9fdca3312;
93 if (c0 & 4) c ^= 0x1bab10e32d;
94 if (c0 & 8) c ^= 0x3706b1677a;
95 if (c0 & 16) c ^= 0x644d626ffd;
114 static std::string INPUT_CHARSET =
115 "0123456789()[],'/*abcdefgh@:$%{}"
116 "IJKLMNOPQRSTUVWXYZ&+-.;<=>?!^_|~"
117 "ijklmnopqrstuvwxyzABCDEFGH`#\"\\ ";
120 static std::string CHECKSUM_CHARSET =
"qpzry9x8gf2tvdw0s3jn54khce6mua7l";
125 for (
auto ch : span) {
126 auto pos = INPUT_CHARSET.find(ch);
127 if (pos == std::string::npos)
return "";
129 cls = cls * 3 + (pos >> 5);
130 if (++clscount == 3) {
137 if (clscount > 0) c =
PolyMod(c, cls);
138 for (
int j = 0; j < 8; ++j) c =
PolyMod(c, 0);
141 std::string
ret(8,
' ');
142 for (
int j = 0; j < 8; ++j)
ret[j] = CHECKSUM_CHARSET[(c >> (5 * (7 - j))) & 31];
146 std::string AddChecksum(
const std::string& str) {
return str +
"#" + DescriptorChecksum(str); }
152 typedef std::vector<uint32_t> KeyPath;
155 struct PubkeyProvider
160 uint32_t m_expr_index;
163 explicit PubkeyProvider(uint32_t exp_index) : m_expr_index(exp_index) {}
165 virtual ~PubkeyProvider() =
default;
170 bool operator<(PubkeyProvider& other)
const {
176 other.GetPubKey(0, dummy, b, dummy_info);
189 virtual bool IsRange()
const = 0;
192 virtual size_t GetSize()
const = 0;
195 virtual std::string
ToString()
const = 0;
198 virtual bool ToPrivateString(
const SigningProvider& arg, std::string& out)
const = 0;
207 class OriginPubkeyProvider final :
public PubkeyProvider
210 std::unique_ptr<PubkeyProvider> m_provider;
212 std::string OriginString()
const
218 OriginPubkeyProvider(uint32_t exp_index,
KeyOriginInfo info, std::unique_ptr<PubkeyProvider> provider) : PubkeyProvider(exp_index), m_origin(
std::move(info)), m_provider(
std::move(provider)) {}
221 if (!m_provider->GetPubKey(pos, arg, key, info, read_cache, write_cache))
return false;
222 std::copy(std::begin(m_origin.fingerprint), std::end(m_origin.fingerprint), info.
fingerprint);
223 info.
path.insert(info.
path.begin(), m_origin.path.begin(), m_origin.path.end());
226 bool IsRange()
const override {
return m_provider->IsRange(); }
227 size_t GetSize()
const override {
return m_provider->GetSize(); }
228 std::string
ToString()
const override {
return "[" + OriginString() +
"]" + m_provider->ToString(); }
232 if (!m_provider->ToPrivateString(arg, sub))
return false;
233 ret =
"[" + OriginString() +
"]" + std::move(sub);
239 if (!m_provider->ToNormalizedString(arg, sub, cache))
return false;
245 ret =
"[" + OriginString() + std::move(sub);
247 ret =
"[" + OriginString() +
"]" + std::move(sub);
253 return m_provider->GetPrivKey(pos, arg, key);
258 class ConstPubkeyProvider final :
public PubkeyProvider
264 ConstPubkeyProvider(uint32_t exp_index,
const CPubKey& pubkey,
bool xonly) : PubkeyProvider(exp_index), m_pubkey(pubkey), m_xonly(xonly) {}
269 CKeyID keyid = m_pubkey.GetID();
273 bool IsRange()
const override {
return false; }
274 size_t GetSize()
const override {
return m_pubkey.size(); }
275 std::string
ToString()
const override {
return m_xonly ?
HexStr(m_pubkey).substr(2) :
HexStr(m_pubkey); }
280 for (
const auto& keyid :
XOnlyPubKey(m_pubkey).GetKeyIDs()) {
285 arg.
GetKey(m_pubkey.GetID(), key);
287 if (!key.
IsValid())
return false;
298 return arg.
GetKey(m_pubkey.GetID(), key);
302 enum class DeriveType {
309 class BIP32PubkeyProvider final :
public PubkeyProvider
319 if (!arg.
GetKey(m_root_extkey.pubkey.GetID(), key))
return false;
320 ret.nDepth = m_root_extkey.nDepth;
321 std::copy(m_root_extkey.vchFingerprint, m_root_extkey.vchFingerprint +
sizeof(
ret.vchFingerprint),
ret.vchFingerprint);
322 ret.nChild = m_root_extkey.nChild;
323 ret.chaincode = m_root_extkey.chaincode;
331 if (!GetExtKey(arg, xprv))
return false;
332 for (
auto entry : m_path) {
333 if (!xprv.
Derive(xprv, entry))
return false;
335 last_hardened = xprv;
341 bool IsHardened()
const
343 if (m_derive == DeriveType::HARDENED)
return true;
344 for (
auto entry : m_path) {
345 if (entry >> 31)
return true;
351 BIP32PubkeyProvider(uint32_t exp_index,
const CExtPubKey& extkey, KeyPath path, DeriveType derive) : PubkeyProvider(exp_index), m_root_extkey(extkey), m_path(
std::move(path)), m_derive(derive) {}
352 bool IsRange()
const override {
return m_derive != DeriveType::NO; }
353 size_t GetSize()
const override {
return 33; }
358 CKeyID keyid = m_root_extkey.pubkey.GetID();
360 parent_info.
path = m_path;
364 if (m_derive == DeriveType::UNHARDENED) final_info_out_tmp.
path.push_back((uint32_t)pos);
365 if (m_derive == DeriveType::HARDENED) final_info_out_tmp.
path.push_back(((uint32_t)pos) | 0x80000000L);
373 if (!read_cache->GetCachedDerivedExtPubKey(m_expr_index, pos, final_extkey)) {
374 if (m_derive == DeriveType::HARDENED)
return false;
376 if (!read_cache->GetCachedParentExtPubKey(m_expr_index, parent_extkey))
return false;
377 final_extkey = parent_extkey;
378 if (m_derive == DeriveType::UNHARDENED) der = parent_extkey.
Derive(final_extkey, pos);
380 }
else if (IsHardened()) {
383 if (!GetDerivedExtKey(arg, xprv, lh_xprv))
return false;
384 parent_extkey = xprv.
Neuter();
385 if (m_derive == DeriveType::UNHARDENED) der = xprv.
Derive(xprv, pos);
386 if (m_derive == DeriveType::HARDENED) der = xprv.
Derive(xprv, pos | 0x80000000UL);
387 final_extkey = xprv.
Neuter();
389 last_hardened_extkey = lh_xprv.
Neuter();
392 for (
auto entry : m_path) {
393 if (!parent_extkey.
Derive(parent_extkey, entry))
return false;
395 final_extkey = parent_extkey;
396 if (m_derive == DeriveType::UNHARDENED) der = parent_extkey.
Derive(final_extkey, pos);
397 assert(m_derive != DeriveType::HARDENED);
399 if (!der)
return false;
401 final_info_out = final_info_out_tmp;
402 key_out = final_extkey.
pubkey;
406 if (m_derive != DeriveType::HARDENED) {
407 write_cache->CacheParentExtPubKey(m_expr_index, parent_extkey);
410 write_cache->CacheLastHardenedExtPubKey(m_expr_index, last_hardened_extkey);
412 }
else if (final_info_out.
path.size() > 0) {
413 write_cache->CacheDerivedExtPubKey(m_expr_index, pos, final_extkey);
419 std::string
ToString()
const override
424 if (m_derive == DeriveType::HARDENED)
ret +=
'\'';
428 bool ToPrivateString(
const SigningProvider& arg, std::string& out)
const override
431 if (!GetExtKey(arg, key))
return false;
435 if (m_derive == DeriveType::HARDENED) out +=
'\'';
442 if (m_derive == DeriveType::HARDENED) {
447 int i = (int)m_path.size() - 1;
448 for (; i >= 0; --i) {
449 if (m_path.at(i) >> 31) {
461 for (;
k <= i; ++
k) {
463 origin.
path.push_back(m_path.at(
k));
467 for (;
k < (int)m_path.size(); ++
k) {
468 end_path.push_back(m_path.at(
k));
471 CKeyID id = m_root_extkey.pubkey.GetID();
472 std::copy(
id.begin(),
id.begin() + 4, origin.
fingerprint);
477 if (cache !=
nullptr) {
483 if (!GetDerivedExtKey(arg, xprv, lh_xprv))
return false;
493 assert(m_derive == DeriveType::UNHARDENED);
501 if (!GetDerivedExtKey(arg, extkey, dummy))
return false;
502 if (m_derive == DeriveType::UNHARDENED && !extkey.
Derive(extkey, pos))
return false;
503 if (m_derive == DeriveType::HARDENED && !extkey.
Derive(extkey, pos | 0x80000000UL))
return false;
514 const std::vector<std::unique_ptr<PubkeyProvider>> m_pubkey_args;
516 const std::string m_name;
522 const std::vector<std::unique_ptr<DescriptorImpl>> m_subdescriptor_args;
525 virtual std::string ToStringExtra()
const {
return ""; }
540 DescriptorImpl(std::vector<std::unique_ptr<PubkeyProvider>> pubkeys,
const std::string&
name) : m_pubkey_args(
std::move(pubkeys)), m_name(
name), m_subdescriptor_args() {}
541 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))) {}
542 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)) {}
544 enum class StringType
553 for (
const auto& arg : m_subdescriptor_args) {
554 if (!arg->IsSolvable())
return false;
561 for (
const auto& pubkey : m_pubkey_args) {
562 if (pubkey->IsRange())
return true;
564 for (
const auto& arg : m_subdescriptor_args) {
565 if (arg->IsRange())
return true;
573 for (
const auto& scriptarg : m_subdescriptor_args) {
574 if (pos++)
ret +=
",";
576 if (!scriptarg->ToStringHelper(arg, tmp, type, cache))
return false;
584 std::string extra = ToStringExtra();
585 size_t pos = extra.size() > 0 ? 1 : 0;
586 std::string
ret = m_name +
"(" + extra;
587 for (
const auto& pubkey : m_pubkey_args) {
588 if (pos++)
ret +=
",";
591 case StringType::NORMALIZED:
592 if (!pubkey->ToNormalizedString(*arg, tmp, cache))
return false;
594 case StringType::PRIVATE:
595 if (!pubkey->ToPrivateString(*arg, tmp))
return false;
597 case StringType::PUBLIC:
598 tmp = pubkey->ToString();
603 std::string subscript;
604 if (!ToStringSubScriptHelper(arg, subscript, type, cache))
return false;
605 if (pos && subscript.size())
ret +=
',';
606 out = std::move(
ret) + std::move(subscript) +
")";
613 ToStringHelper(
nullptr,
ret, StringType::PUBLIC);
614 return AddChecksum(
ret);
619 bool ret = ToStringHelper(&arg, out, StringType::PRIVATE);
620 out = AddChecksum(out);
626 bool ret = ToStringHelper(&arg, out, StringType::NORMALIZED, cache);
627 out = AddChecksum(out);
633 std::vector<std::pair<CPubKey, KeyOriginInfo>> entries;
634 entries.reserve(m_pubkey_args.size());
637 for (
const auto& p : m_pubkey_args) {
638 entries.emplace_back();
639 if (!p->GetPubKey(pos, arg, entries.back().first, entries.back().second, read_cache, write_cache))
return false;
641 std::vector<CScript> subscripts;
643 for (
const auto& subarg : m_subdescriptor_args) {
644 std::vector<CScript> outscripts;
645 if (!subarg->ExpandHelper(pos, arg, read_cache, outscripts, subprovider, write_cache))
return false;
646 assert(outscripts.size() == 1);
647 subscripts.emplace_back(std::move(outscripts[0]));
649 out.
Merge(std::move(subprovider));
651 std::vector<CPubKey> pubkeys;
652 pubkeys.reserve(entries.size());
653 for (
auto& entry : entries) {
654 pubkeys.push_back(entry.first);
655 out.
origins.emplace(entry.first.GetID(), std::make_pair<CPubKey, KeyOriginInfo>(
CPubKey(entry.first), std::move(entry.second)));
658 output_scripts = MakeScripts(pubkeys,
Span{subscripts}, out);
664 return ExpandHelper(pos, provider,
nullptr, output_scripts, out, write_cache);
674 for (
const auto& p : m_pubkey_args) {
676 if (!p->GetPrivKey(pos, provider, key))
continue;
679 for (
const auto& arg : m_subdescriptor_args) {
680 arg->ExpandPrivate(pos, provider, out);
684 std::optional<OutputType>
GetOutputType()
const override {
return std::nullopt; }
688 class AddressDescriptor final :
public DescriptorImpl
692 std::string ToStringExtra()
const override {
return EncodeDestination(m_destination); }
695 AddressDescriptor(
CTxDestination destination) : DescriptorImpl({},
"addr"), m_destination(std::move(destination)) {}
696 bool IsSolvable() const final {
return false; }
702 bool IsSingleType() const final {
return true; }
703 bool ToPrivateString(
const SigningProvider& arg, std::string& out)
const final {
return false; }
707 class RawDescriptor final :
public DescriptorImpl
711 std::string ToStringExtra()
const override {
return HexStr(m_script); }
714 RawDescriptor(
CScript script) : DescriptorImpl({},
"raw"), m_script(std::move(script)) {}
715 bool IsSolvable() const final {
return false; }
723 bool IsSingleType() const final {
return true; }
724 bool ToPrivateString(
const SigningProvider& arg, std::string& out)
const final {
return false; }
728 class PKDescriptor final :
public DescriptorImpl
737 return Vector(std::move(script));
743 PKDescriptor(std::unique_ptr<PubkeyProvider> prov,
bool xonly =
false) : DescriptorImpl(
Vector(
std::move(prov)),
"pk"), m_xonly(xonly) {}
744 bool IsSingleType() const final {
return true; }
748 class PKHDescriptor final :
public DescriptorImpl
753 CKeyID id = keys[0].GetID();
754 out.
pubkeys.emplace(
id, keys[0]);
758 PKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(
Vector(
std::move(prov)),
"pkh") {}
760 bool IsSingleType() const final {
return true; }
764 class WPKHDescriptor final :
public DescriptorImpl
769 CKeyID id = keys[0].GetID();
770 out.
pubkeys.emplace(
id, keys[0]);
774 WPKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(
Vector(
std::move(prov)),
"wpkh") {}
776 bool IsSingleType() const final {
return true; }
780 class ComboDescriptor final :
public DescriptorImpl
785 std::vector<CScript>
ret;
786 CKeyID id = keys[0].GetID();
787 out.
pubkeys.emplace(
id, keys[0]);
790 if (keys[0].IsCompressed()) {
793 ret.emplace_back(p2wpkh);
799 ComboDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(
Vector(
std::move(prov)),
"combo") {}
800 bool IsSingleType() const final {
return false; }
804 class MultisigDescriptor final :
public DescriptorImpl
806 const int m_threshold;
809 std::string ToStringExtra()
const override {
return strprintf(
"%i", m_threshold); }
812 std::vector<CPubKey> sorted_keys(keys);
813 std::sort(sorted_keys.begin(), sorted_keys.end());
819 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) {}
820 bool IsSingleType() const final {
return true; }
824 class MultiADescriptor final :
public DescriptorImpl
826 const int m_threshold;
829 std::string ToStringExtra()
const override {
return strprintf(
"%i", m_threshold); }
832 std::vector<XOnlyPubKey> xkeys;
833 for (
const auto& key : keys) xkeys.emplace_back(key);
834 if (m_sorted) std::sort(xkeys.begin(), xkeys.end());
836 for (
size_t i = 1; i < keys.size(); ++i) {
843 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) {}
844 bool IsSingleType() const final {
return true; }
848 class SHDescriptor final :
public DescriptorImpl
858 SHDescriptor(std::unique_ptr<DescriptorImpl> desc) : DescriptorImpl({}, std::move(desc),
"sh") {}
862 assert(m_subdescriptor_args.size() == 1);
866 bool IsSingleType() const final {
return true; }
870 class WSHDescriptor final :
public DescriptorImpl
880 WSHDescriptor(std::unique_ptr<DescriptorImpl> desc) : DescriptorImpl({}, std::move(desc),
"wsh") {}
882 bool IsSingleType() const final {
return true; }
886 class TRDescriptor final :
public DescriptorImpl
888 std::vector<int> m_depths;
894 for (
size_t pos = 0; pos < m_depths.size(); ++pos) {
900 if (!xpk.IsFullyValid())
return {};
904 out.
pubkeys.emplace(keys[0].GetID(), keys[0]);
909 if (m_depths.empty())
return true;
910 std::vector<bool> path;
911 for (
size_t pos = 0; pos < m_depths.size(); ++pos) {
913 while ((
int)path.size() <= m_depths[pos]) {
914 if (path.size())
ret +=
'{';
915 path.push_back(
false);
918 if (!m_subdescriptor_args[pos]->ToStringHelper(arg, tmp, type, cache))
return false;
920 while (!path.empty() && path.back()) {
921 if (path.size() > 1)
ret +=
'}';
924 if (!path.empty()) path.back() =
true;
929 TRDescriptor(std::unique_ptr<PubkeyProvider> internal_key, std::vector<std::unique_ptr<DescriptorImpl>> descs, std::vector<int> depths) :
930 DescriptorImpl(
Vector(
std::move(internal_key)),
std::move(descs),
"tr"), m_depths(
std::move(depths))
932 assert(m_subdescriptor_args.size() == m_depths.size());
935 bool IsSingleType() const final {
return true; }
948 const std::vector<CPubKey>& m_keys;
951 ScriptMaker(
const std::vector<CPubKey>& keys
LIFETIMEBOUND) : m_keys(keys) {}
953 std::vector<unsigned char> ToPKBytes(uint32_t key)
const {
954 return {m_keys[key].begin(), m_keys[key].end()};
957 std::vector<unsigned char> ToPKHBytes(uint32_t key)
const {
958 auto id = m_keys[key].GetID();
959 return {
id.begin(),
id.end()};
970 const std::vector<std::unique_ptr<PubkeyProvider>>& m_pubkeys;
976 : m_arg(arg), m_pubkeys(pubkeys), m_private(priv) {}
978 std::optional<std::string>
ToString(uint32_t key)
const
982 if (!m_pubkeys[key]->ToPrivateString(*m_arg,
ret))
return {};
984 ret = m_pubkeys[key]->ToString();
990 class MiniscriptDescriptor final :
public DescriptorImpl
996 std::vector<CScript> MakeScripts(
const std::vector<CPubKey>& keys,
Span<const CScript> scripts,
999 for (
const auto& key : keys) provider.
pubkeys.emplace(key.GetID(), key);
1007 bool ToStringHelper(
const SigningProvider* arg, std::string& out,
const StringType type,
1010 if (
const auto res =
m_node->ToString(StringMaker(arg, m_pubkey_args, type == StringType::PRIVATE))) {
1017 bool IsSolvable()
const override {
return false; }
1018 bool IsSingleType() const final {
return true; }
1022 class RawTRDescriptor final :
public DescriptorImpl
1027 assert(keys.size() == 1);
1029 if (!xpk.IsFullyValid())
return {};
1034 RawTRDescriptor(std::unique_ptr<PubkeyProvider> output_key) : DescriptorImpl(
Vector(
std::move(output_key)),
"rawtr") {}
1036 bool IsSingleType() const final {
return true; }
1043 enum class ParseScriptContext {
1052 [[nodiscard]]
bool ParseKeyPath(
const std::vector<
Span<const char>>& split, KeyPath& out, std::string&
error)
1054 for (
size_t i = 1; i < split.size(); ++i) {
1056 bool hardened =
false;
1057 if (elem.
size() > 0 && (elem[elem.
size() - 1] ==
'\'' || elem[elem.
size() - 1] ==
'h')) {
1065 }
else if (p > 0x7FFFFFFFUL) {
1069 out.push_back(p | (((uint32_t)hardened) << 31));
1079 bool permit_uncompressed =
ctx == ParseScriptContext::TOP ||
ctx == ParseScriptContext::P2SH;
1080 auto split =
Split(sp,
'/');
1081 std::string str(split[0].begin(), split[0].end());
1082 if (str.size() == 0) {
1083 error =
"No key provided";
1086 if (split.size() == 1) {
1088 std::vector<unsigned char> data =
ParseHex(str);
1090 if (pubkey.IsFullyValid()) {
1091 if (permit_uncompressed || pubkey.IsCompressed()) {
1092 return std::make_unique<ConstPubkeyProvider>(key_exp_index, pubkey,
false);
1094 error =
"Uncompressed keys are not allowed";
1097 }
else if (data.size() == 32 &&
ctx == ParseScriptContext::P2TR) {
1098 unsigned char fullkey[33] = {0x02};
1099 std::copy(data.begin(), data.end(), fullkey + 1);
1100 pubkey.Set(std::begin(fullkey), std::end(fullkey));
1101 if (pubkey.IsFullyValid()) {
1102 return std::make_unique<ConstPubkeyProvider>(key_exp_index, pubkey,
true);
1113 return std::make_unique<ConstPubkeyProvider>(key_exp_index, pubkey,
ctx == ParseScriptContext::P2TR);
1115 error =
"Uncompressed keys are not allowed";
1127 DeriveType type = DeriveType::NO;
1128 if (split.back() ==
Span{
"*"}.
first(1)) {
1130 type = DeriveType::UNHARDENED;
1131 }
else if (split.back() ==
Span{
"*'"}.
first(2) || split.back() ==
Span{
"*h"}.
first(2)) {
1133 type = DeriveType::HARDENED;
1135 if (!ParseKeyPath(split, path,
error))
return nullptr;
1137 extpubkey = extkey.
Neuter();
1140 return std::make_unique<BIP32PubkeyProvider>(key_exp_index, extpubkey, std::move(path), type);
1148 auto origin_split =
Split(sp,
']');
1149 if (origin_split.size() > 2) {
1150 error =
"Multiple ']' characters found for a single pubkey";
1153 if (origin_split.size() == 1)
return ParsePubkeyInner(key_exp_index, origin_split[0],
ctx, out,
error);
1154 if (origin_split[0].empty() || origin_split[0][0] !=
'[') {
1155 error =
strprintf(
"Key origin start '[ character expected but not found, got '%c' instead",
1156 origin_split[0].empty() ?
']' : origin_split[0][0]);
1159 auto slash_split =
Split(origin_split[0].subspan(1),
'/');
1160 if (slash_split[0].size() != 8) {
1161 error =
strprintf(
"Fingerprint is not 4 bytes (%u characters instead of 8 characters)", slash_split[0].size());
1164 std::string fpr_hex = std::string(slash_split[0].begin(), slash_split[0].end());
1165 if (!
IsHex(fpr_hex)) {
1169 auto fpr_bytes =
ParseHex(fpr_hex);
1171 static_assert(
sizeof(info.
fingerprint) == 4,
"Fingerprint must be 4 bytes");
1172 assert(fpr_bytes.size() == 4);
1173 std::copy(fpr_bytes.begin(), fpr_bytes.end(), info.
fingerprint);
1174 if (!ParseKeyPath(slash_split, info.
path,
error))
return nullptr;
1175 auto provider = ParsePubkeyInner(key_exp_index, origin_split[1],
ctx, out,
error);
1176 if (!provider)
return nullptr;
1177 return std::make_unique<OriginPubkeyProvider>(key_exp_index, std::move(info), std::move(provider));
1180 std::unique_ptr<PubkeyProvider> InferPubkey(
const CPubKey& pubkey, ParseScriptContext,
const SigningProvider& provider)
1182 std::unique_ptr<PubkeyProvider> key_provider = std::make_unique<ConstPubkeyProvider>(0, pubkey,
false);
1185 return std::make_unique<OriginPubkeyProvider>(0, std::move(info), std::move(key_provider));
1187 return key_provider;
1193 std::copy(xkey.
begin(), xkey.
end(), full_key + 1);
1195 std::unique_ptr<PubkeyProvider> key_provider = std::make_unique<ConstPubkeyProvider>(0, pubkey,
true);
1198 return std::make_unique<OriginPubkeyProvider>(0, std::move(info), std::move(key_provider));
1200 return key_provider;
1208 using Key = uint32_t;
1214 mutable std::vector<std::unique_ptr<PubkeyProvider>> m_keys;
1216 mutable std::string m_key_parsing_error;
1220 bool KeyCompare(
const Key& a,
const Key& b)
const {
1221 return *m_keys.at(a) < *m_keys.at(b);
1224 template<
typename I> std::optional<Key>
FromString(I begin, I end)
const
1227 Key key = m_keys.
size();
1228 auto pk = ParsePubkey(key, {&*begin, &*end}, ParseScriptContext::P2WSH, *m_out, m_key_parsing_error);
1230 m_keys.push_back(std::move(pk));
1234 std::optional<std::string>
ToString(
const Key& key)
const
1236 return m_keys.at(key)->ToString();
1239 template<
typename I> std::optional<Key> FromPKBytes(I begin, I end)
const
1244 Key key = m_keys.size();
1245 m_keys.push_back(InferPubkey(pubkey, ParseScriptContext::P2WSH, *m_in));
1251 template<
typename I> std::optional<Key> FromPKHBytes(I begin, I end)
const
1253 assert(end - begin == 20);
1256 std::copy(begin, end, hash.
begin());
1260 Key key = m_keys.
size();
1261 m_keys.push_back(InferPubkey(pubkey, ParseScriptContext::P2WSH, *m_in));
1273 auto expr =
Expr(sp);
1274 if (
Func(
"pk", expr)) {
1275 auto pubkey = ParsePubkey(key_exp_index, expr,
ctx, out,
error);
1281 return std::make_unique<PKDescriptor>(std::move(pubkey),
ctx == ParseScriptContext::P2TR);
1283 if ((
ctx == ParseScriptContext::TOP ||
ctx == ParseScriptContext::P2SH ||
ctx == ParseScriptContext::P2WSH) &&
Func(
"pkh", expr)) {
1284 auto pubkey = ParsePubkey(key_exp_index, expr,
ctx, out,
error);
1290 return std::make_unique<PKHDescriptor>(std::move(pubkey));
1291 }
else if (
Func(
"pkh", expr)) {
1292 error =
"Can only have pkh at top level, in sh(), or in wsh()";
1295 if (
ctx == ParseScriptContext::TOP &&
Func(
"combo", expr)) {
1296 auto pubkey = ParsePubkey(key_exp_index, expr,
ctx, out,
error);
1302 return std::make_unique<ComboDescriptor>(std::move(pubkey));
1303 }
else if (
Func(
"combo", expr)) {
1304 error =
"Can only have combo() at top level";
1307 const bool multi =
Func(
"multi", expr);
1308 const bool sortedmulti = !multi &&
Func(
"sortedmulti", expr);
1309 const bool multi_a = !(multi || sortedmulti) &&
Func(
"multi_a", expr);
1310 const bool sortedmulti_a = !(multi || sortedmulti || multi_a) &&
Func(
"sortedmulti_a", expr);
1311 if (((
ctx == ParseScriptContext::TOP ||
ctx == ParseScriptContext::P2SH ||
ctx == ParseScriptContext::P2WSH) && (multi || sortedmulti)) ||
1312 (
ctx == ParseScriptContext::P2TR && (multi_a || sortedmulti_a))) {
1313 auto threshold =
Expr(expr);
1315 std::vector<std::unique_ptr<PubkeyProvider>> providers;
1316 if (!
ParseUInt32(std::string(threshold.begin(), threshold.end()), &thres)) {
1317 error =
strprintf(
"Multi threshold '%s' is not valid", std::string(threshold.begin(), threshold.end()));
1320 size_t script_size = 0;
1321 while (expr.size()) {
1322 if (!
Const(
",", expr)) {
1326 auto arg =
Expr(expr);
1327 auto pk = ParsePubkey(key_exp_index, arg,
ctx, out,
error);
1332 script_size += pk->GetSize() + 1;
1333 providers.emplace_back(std::move(pk));
1342 }
else if (thres < 1) {
1343 error =
strprintf(
"Multisig threshold cannot be %d, must be at least 1", thres);
1345 }
else if (thres > providers.size()) {
1346 error =
strprintf(
"Multisig threshold cannot be larger than the number of keys; threshold is %d but only %u keys specified", thres, providers.size());
1349 if (
ctx == ParseScriptContext::TOP) {
1350 if (providers.size() > 3) {
1351 error =
strprintf(
"Cannot have %u pubkeys in bare multisig; only at most 3 pubkeys", providers.size());
1355 if (
ctx == ParseScriptContext::P2SH) {
1362 if (multi || sortedmulti) {
1363 return std::make_unique<MultisigDescriptor>(thres, std::move(providers), sortedmulti);
1365 return std::make_unique<MultiADescriptor>(thres, std::move(providers), sortedmulti_a);
1367 }
else if (multi || sortedmulti) {
1368 error =
"Can only have multi/sortedmulti at top level, in sh(), or in wsh()";
1370 }
else if (multi_a || sortedmulti_a) {
1371 error =
"Can only have multi_a/sortedmulti_a inside tr()";
1374 if ((
ctx == ParseScriptContext::TOP ||
ctx == ParseScriptContext::P2SH) &&
Func(
"wpkh", expr)) {
1375 auto pubkey = ParsePubkey(key_exp_index, expr, ParseScriptContext::P2WPKH, out,
error);
1381 return std::make_unique<WPKHDescriptor>(std::move(pubkey));
1382 }
else if (
Func(
"wpkh", expr)) {
1383 error =
"Can only have wpkh() at top level or inside sh()";
1386 if (
ctx == ParseScriptContext::TOP &&
Func(
"sh", expr)) {
1387 auto desc =
ParseScript(key_exp_index, expr, ParseScriptContext::P2SH, out,
error);
1388 if (!desc || expr.size())
return nullptr;
1389 return std::make_unique<SHDescriptor>(std::move(desc));
1390 }
else if (
Func(
"sh", expr)) {
1391 error =
"Can only have sh() at top level";
1394 if ((
ctx == ParseScriptContext::TOP ||
ctx == ParseScriptContext::P2SH) &&
Func(
"wsh", expr)) {
1395 auto desc =
ParseScript(key_exp_index, expr, ParseScriptContext::P2WSH, out,
error);
1396 if (!desc || expr.size())
return nullptr;
1397 return std::make_unique<WSHDescriptor>(std::move(desc));
1398 }
else if (
Func(
"wsh", expr)) {
1399 error =
"Can only have wsh() at top level or inside sh()";
1402 if (
ctx == ParseScriptContext::TOP &&
Func(
"addr", expr)) {
1405 error =
"Address is not valid";
1408 return std::make_unique<AddressDescriptor>(std::move(dest));
1409 }
else if (
Func(
"addr", expr)) {
1410 error =
"Can only have addr() at top level";
1413 if (
ctx == ParseScriptContext::TOP &&
Func(
"tr", expr)) {
1414 auto arg =
Expr(expr);
1415 auto internal_key = ParsePubkey(key_exp_index, arg, ParseScriptContext::P2TR, out,
error);
1416 if (!internal_key) {
1421 std::vector<std::unique_ptr<DescriptorImpl>> subscripts;
1422 std::vector<int> depths;
1424 if (!
Const(
",", expr)) {
1431 std::vector<bool> branches;
1436 while (
Const(
"{", expr)) {
1437 branches.push_back(
false);
1444 auto sarg =
Expr(expr);
1445 subscripts.emplace_back(
ParseScript(key_exp_index, sarg, ParseScriptContext::P2TR, out,
error));
1446 if (!subscripts.back())
return nullptr;
1447 depths.push_back(branches.size());
1449 while (branches.size() && branches.back()) {
1450 if (!
Const(
"}", expr)) {
1454 branches.pop_back();
1457 if (branches.size() && !branches.back()) {
1458 if (!
Const(
",", expr)) {
1462 branches.back() =
true;
1464 }
while (branches.size());
1472 return std::make_unique<TRDescriptor>(std::move(internal_key), std::move(subscripts), std::move(depths));
1473 }
else if (
Func(
"tr", expr)) {
1474 error =
"Can only have tr at top level";
1477 if (
ctx == ParseScriptContext::TOP &&
Func(
"rawtr", expr)) {
1478 auto arg =
Expr(expr);
1483 auto output_key = ParsePubkey(key_exp_index, arg, ParseScriptContext::P2TR, out,
error);
1484 if (!output_key)
return nullptr;
1486 return std::make_unique<RawTRDescriptor>(std::move(output_key));
1487 }
else if (
Func(
"rawtr", expr)) {
1488 error =
"Can only have rawtr at top level";
1491 if (
ctx == ParseScriptContext::TOP &&
Func(
"raw", expr)) {
1492 std::string str(expr.begin(), expr.end());
1494 error =
"Raw script is not hex";
1498 return std::make_unique<RawDescriptor>(
CScript(bytes.begin(), bytes.end()));
1499 }
else if (
Func(
"raw", expr)) {
1500 error =
"Can only have raw() at top level";
1505 KeyParser parser(&out,
nullptr);
1508 if (
ctx != ParseScriptContext::P2WSH) {
1509 error =
"Miniscript expressions can only be used in wsh";
1512 if (parser.m_key_parsing_error !=
"") {
1513 error = std::move(parser.m_key_parsing_error);
1516 if (!
node->IsSane()) {
1518 auto insane_node =
node.get();
1519 if (
const auto sub =
node->FindInsaneSub()) insane_node = sub;
1520 if (
const auto str = insane_node->ToString(parser))
error = *str;
1521 if (!insane_node->IsValid()) {
1522 error +=
" is invalid";
1524 error +=
" is not sane";
1525 if (!insane_node->IsNonMalleable()) {
1526 error +=
": malleable witnesses exist";
1527 }
else if (insane_node ==
node.get() && !insane_node->NeedsSignature()) {
1528 error +=
": witnesses without signature exist";
1529 }
else if (!insane_node->CheckTimeLocksMix()) {
1530 error +=
": contains mixes of timelocks expressed in blocks and seconds";
1531 }
else if (!insane_node->CheckDuplicateKey()) {
1532 error +=
": contains duplicate public keys";
1533 }
else if (!insane_node->ValidSatisfactions()) {
1534 error +=
": needs witnesses that may exceed resource limits";
1539 return std::make_unique<MiniscriptDescriptor>(std::move(parser.m_keys), std::move(
node));
1542 if (
ctx == ParseScriptContext::P2SH) {
1543 error =
"A function is needed within P2SH";
1545 }
else if (
ctx == ParseScriptContext::P2WSH) {
1546 error =
"A function is needed within P2WSH";
1549 error =
strprintf(
"'%s' is not a valid descriptor function", std::string(expr.begin(), expr.end()));
1553 std::unique_ptr<DescriptorImpl> InferMultiA(
const CScript& script, ParseScriptContext
ctx,
const SigningProvider& provider)
1556 if (!match)
return {};
1557 std::vector<std::unique_ptr<PubkeyProvider>> keys;
1558 keys.reserve(match->second.size());
1559 for (
const auto keyspan : match->second) {
1560 if (keyspan.size() != 32)
return {};
1561 auto key = InferXOnlyPubkey(
XOnlyPubKey{keyspan},
ctx, provider);
1562 if (!key)
return {};
1563 keys.push_back(std::move(key));
1565 return std::make_unique<MultiADescriptor>(match->first, std::move(keys));
1568 std::unique_ptr<DescriptorImpl> InferScript(
const CScript& script, ParseScriptContext
ctx,
const SigningProvider& provider)
1570 if (
ctx == ParseScriptContext::P2TR && script.
size() == 34 && script[0] == 32 && script[33] ==
OP_CHECKSIG) {
1572 return std::make_unique<PKDescriptor>(InferXOnlyPubkey(key,
ctx, provider),
true);
1575 if (
ctx == ParseScriptContext::P2TR) {
1576 auto ret = InferMultiA(script,
ctx, provider);
1580 std::vector<std::vector<unsigned char>> data;
1583 if (txntype ==
TxoutType::PUBKEY && (
ctx == ParseScriptContext::TOP ||
ctx == ParseScriptContext::P2SH ||
ctx == ParseScriptContext::P2WSH)) {
1586 return std::make_unique<PKDescriptor>(InferPubkey(pubkey,
ctx, provider));
1589 if (txntype ==
TxoutType::PUBKEYHASH && (
ctx == ParseScriptContext::TOP ||
ctx == ParseScriptContext::P2SH ||
ctx == ParseScriptContext::P2WSH)) {
1593 if (provider.
GetPubKey(keyid, pubkey)) {
1594 return std::make_unique<PKHDescriptor>(InferPubkey(pubkey,
ctx, provider));
1601 if (provider.
GetPubKey(keyid, pubkey)) {
1602 return std::make_unique<WPKHDescriptor>(InferPubkey(pubkey,
ctx, provider));
1605 if (txntype ==
TxoutType::MULTISIG && (
ctx == ParseScriptContext::TOP ||
ctx == ParseScriptContext::P2SH ||
ctx == ParseScriptContext::P2WSH)) {
1606 std::vector<std::unique_ptr<PubkeyProvider>> providers;
1607 for (
size_t i = 1; i + 1 < data.size(); ++i) {
1609 providers.push_back(InferPubkey(pubkey,
ctx, provider));
1611 return std::make_unique<MultisigDescriptor>((
int)data[0][0], std::move(providers));
1617 if (provider.
GetCScript(scriptid, subscript)) {
1618 auto sub = InferScript(subscript, ParseScriptContext::P2SH, provider);
1619 if (sub)
return std::make_unique<SHDescriptor>(std::move(sub));
1625 if (provider.
GetCScript(scriptid, subscript)) {
1626 auto sub = InferScript(subscript, ParseScriptContext::P2WSH, provider);
1627 if (sub)
return std::make_unique<WSHDescriptor>(std::move(sub));
1633 std::copy(data[0].begin(), data[0].end(), pubkey.
begin());
1642 std::vector<std::unique_ptr<DescriptorImpl>> subscripts;
1643 std::vector<int> depths;
1644 for (
const auto& [depth, script, leaf_ver] : *tree) {
1645 std::unique_ptr<DescriptorImpl> subdesc;
1647 subdesc = InferScript(
CScript(script.
begin(), script.
end()), ParseScriptContext::P2TR, provider);
1653 subscripts.push_back(std::move(subdesc));
1654 depths.push_back(depth);
1658 auto key = InferXOnlyPubkey(tap.
internal_key, ParseScriptContext::P2TR, provider);
1659 return std::make_unique<TRDescriptor>(std::move(key), std::move(subscripts), std::move(depths));
1665 auto key = InferXOnlyPubkey(pubkey, ParseScriptContext::P2TR, provider);
1667 return std::make_unique<RawTRDescriptor>(std::move(key));
1672 if (
ctx == ParseScriptContext::P2WSH) {
1673 KeyParser parser(
nullptr, &provider);
1676 return std::make_unique<MiniscriptDescriptor>(std::move(parser.m_keys), std::move(
node));
1683 return std::make_unique<AddressDescriptor>(std::move(dest));
1687 return std::make_unique<RawDescriptor>(script);
1698 auto check_split =
Split(sp,
'#');
1699 if (check_split.size() > 2) {
1700 error =
"Multiple '#' symbols";
1703 if (check_split.size() == 1 && require_checksum){
1704 error =
"Missing checksum";
1707 if (check_split.size() == 2) {
1708 if (check_split[1].size() != 8) {
1709 error =
strprintf(
"Expected 8 character checksum, not %u characters", check_split[1].size());
1713 auto checksum = DescriptorChecksum(check_split[0]);
1714 if (checksum.empty()) {
1715 error =
"Invalid characters in payload";
1718 if (check_split.size() == 2) {
1719 if (!std::equal(checksum.begin(), checksum.end(), check_split[1].begin())) {
1720 error =
strprintf(
"Provided checksum '%s' does not match computed checksum '%s'", std::string(check_split[1].begin(), check_split[1].end()), checksum);
1724 if (out_checksum) *out_checksum = std::move(checksum);
1725 sp = check_split[0];
1733 uint32_t key_exp_index = 0;
1735 if (sp.
size() == 0 &&
ret)
return std::unique_ptr<Descriptor>(std::move(
ret));
1750 return InferScript(script, ParseScriptContext::TOP, provider);
1761 xpubs[der_index] = xpub;
1781 const auto& der_it = key_exp_it->second.find(der_index);
1782 if (der_it == key_exp_it->second.end())
return false;
1783 xpub = der_it->second;
1801 if (xpub != parent_xpub_pair.second) {
1802 throw std::runtime_error(std::string(__func__) +
": New cached parent xpub does not match already cached parent xpub");
1810 for (
const auto& derived_xpub_pair : derived_xpub_map_pair.second) {
1813 if (xpub != derived_xpub_pair.second) {
1814 throw std::runtime_error(std::string(__func__) +
": New cached derived xpub does not match already cached derived xpub");
1818 CacheDerivedExtPubKey(derived_xpub_map_pair.first, derived_xpub_pair.first, derived_xpub_pair.second);
1819 diff.
CacheDerivedExtPubKey(derived_xpub_map_pair.first, derived_xpub_pair.first, derived_xpub_pair.second);
1825 if (xpub != lh_xpub_pair.second) {
1826 throw std::runtime_error(std::string(__func__) +
": New cached last hardened xpub does not match already cached last hardened xpub");
std::string FormatHDKeypath(const std::vector< uint32_t > &path)
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.
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
static constexpr unsigned int COMPRESSED_SIZE
unsigned int size() const
Simple read-only vector-like interface to the pubkey data.
Serialized script, used inside transaction inputs and outputs.
A reference to a CScript: the Hash160 of its serialization (see script.h)
Cache for single descriptor's derived extended pubkeys.
bool GetCachedParentExtPubKey(uint32_t key_exp_pos, CExtPubKey &xpub) const
Retrieve a cached parent xpub.
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.
const ExtPubKeyMap GetCachedLastHardenedExtPubKeys() const
Retrieve all cached last hardened xpubs.
DescriptorCache MergeAndDiff(const DescriptorCache &other)
Combine another DescriptorCache into this one.
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.
const ExtPubKeyMap GetCachedParentExtPubKeys() const
Retrieve all cached parent xpubs.
const std::unordered_map< uint32_t, ExtPubKeyMap > GetCachedDerivedExtPubKeys() const
Retrieve all cached derived xpubs.
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 C * end() const noexcept
constexpr C * begin() const noexcept
CONSTEXPR_IF_NOT_DEBUG Span< C > first(std::size_t count) 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
bool IsFullyValid() const
Determine if this pubkey is fully valid.
const unsigned char * end() const
CScript ParseScript(const std::string &s)
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.
std::string GetDescriptorChecksum(const std::string &descriptor)
Get the checksum for a descriptor.
std::unique_ptr< Descriptor > Parse(const std::string &descriptor, FlatSigningProvider &out, std::string &error, bool require_checksum)
Parse a descriptor string.
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::unordered_map< uint32_t, CExtPubKey > ExtPubKeyMap
uint160 RIPEMD160(Span< const unsigned char > data)
Compute the 160-bit RIPEMD-160 hash of an array.
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)
std::shared_ptr< const Node< Key > > NodeRef
NodeRef< typename Ctx::Key > FromScript(const CScript &script, const Ctx &ctx)
NodeRef< typename Ctx::Key > FromString(const std::string &str, const Ctx &ctx)
Span< const char > Expr(Span< const char > &sp)
Extract the expression that sp begins with.
bool Const(const std::string &str, Span< const char > &sp)
Parse a constant.
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.
static OutputType GetOutputType(TxoutType type, bool is_from_p2sh)
bool operator<(const CNetAddr &a, const CNetAddr &b)
std::optional< OutputType > OutputTypeFromDestination(const CTxDestination &dest)
Get the OutputType for a CTxDestination.
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE
std::vector< unsigned char > ToByteVector(const T &in)
static constexpr unsigned int MAX_PUBKEYS_PER_MULTI_A
The limit of keys in OP_CHECKSIGADD-based scripts.
static const int MAX_PUBKEYS_PER_MULTISIG
static bool GetPubKey(const SigningProvider &provider, const SignatureData &sigdata, const CKeyID &address, CPubKey &pubkey)
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.
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a standard scriptPubKey for the destination address.
CScript GetScriptForRawPubKey(const CPubKey &pubKey)
Generate a P2PK script for the given 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.
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
std::variant< CNoDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, WitnessUnknown > CTxDestination
A txout script template with a specific destination.
std::string ToString(const T &t)
Locale-independent version of std::to_string.
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() const =0
Convert the descriptor back to a string, undoing parsing.
virtual std::optional< OutputType > GetOutputType() const =0
virtual bool ToNormalizedString(const SigningProvider &provider, std::string &out, const DescriptorCache *cache=nullptr) const =0
Convert the descriptor to a normalized string.
virtual bool Expand(int pos, const SigningProvider &provider, std::vector< CScript > &output_scripts, FlatSigningProvider &out, DescriptorCache *write_cache=nullptr) const =0
Expand a descriptor at a specified position.
virtual bool IsRange() const =0
Whether the expansion of this descriptor depends on the position.
virtual bool IsSolvable() const =0
Whether this descriptor has all information about signing ignoring lack of private keys.
virtual void ExpandPrivate(int pos, const SigningProvider &provider, FlatSigningProvider &out) const =0
Expand the private key for a descriptor at a specified position, if possible.
virtual bool ToPrivateString(const SigningProvider &provider, std::string &out) const =0
Convert the descriptor to a private string.
virtual bool ExpandFromCache(int pos, const DescriptorCache &read_cache, std::vector< CScript > &output_scripts, FlatSigningProvider &out) const =0
Expand a descriptor at a specified position using cached expansion data.
FlatSigningProvider & Merge(FlatSigningProvider &&b) LIFETIMEBOUND
std::map< CKeyID, std::pair< CPubKey, KeyOriginInfo > > origins
std::map< CKeyID, CPubKey > pubkeys
std::map< CKeyID, CKey > keys
std::map< CScriptID, CScript > scripts
std::map< XOnlyPubKey, TaprootBuilder > tr_trees
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 error(const char *fmt, const Args &... args)
static secp256k1_context * ctx
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
std::vector< Byte > ParseHex(std::string_view str)
Parse the hex string into bytes (uint8_t or std::byte).
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.