7#include <chainparams.h>
90 c = ((
c & 0x7ffffffff) << 5) ^ val;
127 static std::string
INPUT_CHARSET =
"0123456789()[],'/*abcdefgh@:$%{}"
128 "IJKLMNOPQRSTUVWXYZ&+-.;<=>?!^_|~"
129 "ijklmnopqrstuvwxyzABCDEFGH`#\"\\ ";
139 if (pos == std::string::npos) {
145 cls =
cls * 3 + (pos >> 5);
157 for (
int j = 0;
j < 8; ++
j) {
164 std::string
ret(8,
' ');
165 for (
int j = 0;
j < 8; ++
j) {
179typedef std::vector<uint32_t>
KeyPath;
182struct PubkeyProvider {
207 virtual bool IsRange()
const = 0;
210 virtual size_t GetSize()
const = 0;
213 virtual std::string
ToString()
const = 0;
220 std::string &out)
const = 0;
224 CKey &key)
const = 0;
227class OriginPubkeyProvider
final :
public PubkeyProvider {
229 std::unique_ptr<PubkeyProvider> m_provider;
237 std::unique_ptr<PubkeyProvider> provider)
239 m_provider(
std::
move(provider)) {}
248 std::copy(std::begin(m_origin.fingerprint),
250 info.
path.insert(info.
path.begin(), m_origin.path.begin(),
251 m_origin.path.end());
254 bool IsRange()
const override {
return m_provider->IsRange(); }
255 size_t GetSize()
const override {
return m_provider->GetSize(); }
256 std::string
ToString()
const override {
257 return "[" +
OriginString() +
"]" + m_provider->ToString();
260 std::string &
ret)
const override {
262 if (!m_provider->ToPrivateString(
arg, sub)) {
269 CKey &key)
const override {
270 return m_provider->GetPrivKey(pos,
arg, key);
275class ConstPubkeyProvider
final :
public PubkeyProvider {
280 : PubkeyProvider(
exp_index), m_pubkey(pubkey) {}
292 bool IsRange()
const override {
return false; }
293 size_t GetSize()
const override {
return m_pubkey.size(); }
294 std::string
ToString()
const override {
return HexStr(m_pubkey); }
296 std::string &
ret)
const override {
298 if (!
arg.GetKey(m_pubkey.GetID(), key)) {
305 CKey &key)
const override {
306 return arg.GetKey(m_pubkey.GetID(), key);
310enum class DeriveType {
317class BIP32PubkeyProvider
final :
public PubkeyProvider {
328 if (!
arg.GetKey(m_root_extkey.pubkey.GetID(), key)) {
331 ret.nDepth = m_root_extkey.nDepth;
332 std::copy(m_root_extkey.vchFingerprint,
333 m_root_extkey.vchFingerprint +
sizeof(
ret.vchFingerprint),
335 ret.nChild = m_root_extkey.nChild;
336 ret.chaincode = m_root_extkey.chaincode;
346 for (
auto entry : m_path) {
353 if (m_derive == DeriveType::HARDENED) {
356 for (
auto entry : m_path) {
369 bool IsRange()
const override {
return m_derive != DeriveType::NO; }
370 size_t GetSize()
const override {
return 33; }
378 std::copy(
keyid.begin(),
386 if (m_derive == DeriveType::UNHARDENED) {
389 if (m_derive == DeriveType::HARDENED) {
398 if (!
read_cache->GetCachedDerivedExtPubKey(m_expr_index, pos,
400 if (m_derive == DeriveType::HARDENED) {
404 if (!
read_cache->GetCachedParentExtPubKey(m_expr_index,
409 if (m_derive == DeriveType::UNHARDENED) {
414 m_derive != DeriveType::HARDENED) {
416 if (m_derive == DeriveType::UNHARDENED) {
425 if (m_derive == DeriveType::UNHARDENED) {
428 if (m_derive == DeriveType::HARDENED) {
433 for (
auto entry : m_path) {
438 if (m_derive == DeriveType::UNHARDENED) {
441 assert(m_derive != DeriveType::HARDENED);
457 if (m_derive != DeriveType::HARDENED) {
460 write_cache->CacheDerivedExtPubKey(m_expr_index, pos,
467 std::string
ToString()
const override {
472 if (m_derive == DeriveType::HARDENED) {
479 std::string &out)
const override {
487 if (m_derive == DeriveType::HARDENED) {
494 CKey &key)
const override {
499 if (m_derive == DeriveType::UNHARDENED) {
502 if (m_derive == DeriveType::HARDENED) {
514 const std::vector<std::unique_ptr<PubkeyProvider>> m_pubkey_args;
516 const std::string m_name;
522 const std::unique_ptr<DescriptorImpl> m_subdescriptor_arg;
543 virtual std::vector<CScript>
548 DescriptorImpl(std::vector<std::unique_ptr<PubkeyProvider>> pubkeys,
549 std::unique_ptr<DescriptorImpl> script,
550 const std::string &
name)
552 m_subdescriptor_arg(
std::
move(script)) {}
555 if (m_subdescriptor_arg) {
556 if (!m_subdescriptor_arg->IsSolvable()) {
564 for (
const auto &pubkey : m_pubkey_args) {
565 if (pubkey->IsRange()) {
569 if (m_subdescriptor_arg) {
570 if (m_subdescriptor_arg->IsRange()) {
580 size_t pos =
extra.size() > 0 ? 1 : 0;
581 std::string
ret = m_name +
"(" +
extra;
582 for (
const auto &pubkey : m_pubkey_args) {
588 if (!pubkey->ToPrivateString(*
arg, tmp)) {
592 tmp = pubkey->ToString();
596 if (m_subdescriptor_arg) {
601 if (!m_subdescriptor_arg->ToStringHelper(
arg, tmp, priv)) {
606 out = std::move(
ret) +
")";
617 std::string &out)
const final {
628 std::vector<std::pair<CPubKey, KeyOriginInfo>> entries;
629 entries.reserve(m_pubkey_args.size());
633 for (
const auto &
p : m_pubkey_args) {
634 entries.emplace_back();
635 if (!
p->GetPubKey(pos,
arg, entries.back().first,
641 if (m_subdescriptor_arg) {
651 std::vector<CPubKey> pubkeys;
652 pubkeys.reserve(entries.size());
653 for (
auto &entry : entries) {
654 pubkeys.push_back(entry.first);
657 std::make_pair<CPubKey, KeyOriginInfo>(
658 CPubKey(entry.first), std::move(entry.second)));
660 if (m_subdescriptor_arg) {
691 for (
const auto &
p : m_pubkey_args) {
693 if (!
p->GetPrivKey(pos, provider, key)) {
698 if (m_subdescriptor_arg) {
700 m_subdescriptor_arg->ExpandPrivate(pos, provider,
subprovider);
711class AddressDescriptor
final :
public DescriptorImpl {
718 std::vector<CScript>
MakeScripts(
const std::vector<CPubKey> &,
726 : DescriptorImpl({}, {},
"addr"),
727 m_destination(std::move(destination)) {}
730 std::optional<OutputType> GetOutputType()
const override {
731 switch (m_destination.index()) {
740 bool IsSingleType() const
final {
return true; }
744class RawDescriptor
final :
public DescriptorImpl {
749 std::vector<CScript>
MakeScripts(
const std::vector<CPubKey> &,
757 : DescriptorImpl({}, {},
"raw"), m_script(std::move(script)) {}
760 std::optional<OutputType> GetOutputType()
const override {
763 switch (dest.index()) {
772 bool IsSingleType() const
final {
return true; }
776class PKDescriptor
final :
public DescriptorImpl {
778 std::vector<CScript>
MakeScripts(
const std::vector<CPubKey> &keys,
785 PKDescriptor(std::unique_ptr<PubkeyProvider>
prov)
787 bool IsSingleType() const
final {
return true; }
791class PKHDescriptor
final :
public DescriptorImpl {
793 std::vector<CScript>
MakeScripts(
const std::vector<CPubKey> &keys,
796 CKeyID id = keys[0].GetID();
797 out.
pubkeys.emplace(
id, keys[0]);
802 PKHDescriptor(std::unique_ptr<PubkeyProvider>
prov)
804 std::optional<OutputType> GetOutputType()
const override {
807 bool IsSingleType() const
final {
return true; }
811class ComboDescriptor
final :
public DescriptorImpl {
813 std::vector<CScript>
MakeScripts(
const std::vector<CPubKey> &keys,
816 std::vector<CScript>
ret;
817 CKeyID id = keys[0].GetID();
818 out.
pubkeys.emplace(
id, keys[0]);
827 ComboDescriptor(std::unique_ptr<PubkeyProvider>
prov)
829 bool IsSingleType() const
final {
return false; }
833class MultisigDescriptor
final :
public DescriptorImpl {
834 const int m_threshold;
841 std::vector<CScript>
MakeScripts(
const std::vector<CPubKey> &keys,
854 std::vector<std::unique_ptr<PubkeyProvider>>
providers,
857 sorted ?
"sortedmulti" :
"multi"),
858 m_threshold(
threshold), m_sorted(sorted) {}
859 bool IsSingleType() const
final {
return true; }
863class SHDescriptor
final :
public DescriptorImpl {
865 std::vector<CScript>
MakeScripts(
const std::vector<CPubKey> &,
872 SHDescriptor(std::unique_ptr<DescriptorImpl>
desc)
873 : DescriptorImpl({}, std::move(
desc),
"sh") {}
874 std::optional<OutputType> GetOutputType()
const override {
877 bool IsSingleType() const
final {
return true; }
884enum class ParseScriptContext {
895 for (
size_t i = 1; i <
split.size(); ++i) {
898 if (
elem.size() > 0 &&
906 std::string(
elem.begin(),
elem.end()).c_str());
908 }
else if (
p > 0x7FFFFFFFUL) {
921 std::string &
error) {
925 std::string str(
split[0].begin(),
split[0].end());
926 if (str.size() == 0) {
927 error =
"No key provided";
930 if (
split.size() == 1) {
932 std::vector<uint8_t> data =
ParseHex(str);
934 if (pubkey.IsFullyValid()) {
945 return std::make_unique<ConstPubkeyProvider>(
key_exp_index, pubkey);
955 DeriveType type = DeriveType::NO;
958 type = DeriveType::UNHARDENED;
962 type = DeriveType::HARDENED;
967 if (
extkey.key.IsValid()) {
972 std::move(path), type);
979 std::string &
error) {
984 error =
"Multiple ']' characters found for a single pubkey";
991 error =
strprintf(
"Key origin start '[ character expected but not "
992 "found, got '%c' instead",
1000 error =
strprintf(
"Fingerprint is not 4 bytes (%u characters instead "
1013 static_assert(
sizeof(info.
fingerprint) == 4,
"Fingerprint must be 4 bytes");
1024 return std::make_unique<OriginPubkeyProvider>(
1031 ParseScriptContext
ctx,
1033 std::string &
error) {
1043 return std::make_unique<PKDescriptor>(std::move(pubkey));
1050 return std::make_unique<PKHDescriptor>(std::move(pubkey));
1052 if (
ctx == ParseScriptContext::TOP &&
Func(
"combo",
expr)) {
1057 return std::make_unique<ComboDescriptor>(std::move(pubkey));
1058 }
else if (
ctx != ParseScriptContext::TOP &&
Func(
"combo",
expr)) {
1059 error =
"Cannot have combo in non-top level";
1065 std::vector<std::unique_ptr<PubkeyProvider>>
providers;
1069 "Multi threshold '%s' is not valid",
1074 while (
expr.size()) {
1090 "between 1 and 16 keys, inclusive",
1093 }
else if (
thres < 1) {
1095 "Multisig threshold cannot be %d, must be at least 1",
thres);
1099 strprintf(
"Multisig threshold cannot be larger than the number "
1100 "of keys; threshold is %d but only %u keys specified",
1104 if (
ctx == ParseScriptContext::TOP) {
1107 "only at most 3 pubkeys",
1112 if (
ctx == ParseScriptContext::P2SH) {
1115 "larger than %d bytes",
1120 return std::make_unique<MultisigDescriptor>(
thres, std::move(
providers),
1123 if (
ctx == ParseScriptContext::TOP &&
Func(
"sh",
expr)) {
1129 return std::make_unique<SHDescriptor>(std::move(
desc));
1130 }
else if (
ctx != ParseScriptContext::TOP &&
Func(
"sh",
expr)) {
1131 error =
"Cannot have sh in non-top level";
1134 if (
ctx == ParseScriptContext::TOP &&
Func(
"addr",
expr)) {
1138 error =
"Address is not valid";
1141 return std::make_unique<AddressDescriptor>(std::move(dest));
1143 if (
ctx == ParseScriptContext::TOP &&
Func(
"raw",
expr)) {
1144 std::string str(
expr.begin(),
expr.end());
1146 error =
"Raw script is not hex";
1150 return std::make_unique<RawDescriptor>(
1151 CScript(bytes.begin(), bytes.end()));
1153 if (
ctx == ParseScriptContext::P2SH) {
1154 error =
"A function is needed within P2SH";
1158 std::string(
expr.begin(),
expr.end()));
1166 std::make_unique<ConstPubkeyProvider>(0, pubkey);
1169 return std::make_unique<OriginPubkeyProvider>(0, std::move(info),
1176 ParseScriptContext
ctx,
1178 std::vector<std::vector<uint8_t>> data;
1184 return std::make_unique<PKDescriptor>(
1193 return std::make_unique<PKHDescriptor>(
1198 std::vector<std::unique_ptr<PubkeyProvider>>
providers;
1199 for (
size_t i = 1; i + 1 < data.size(); ++i) {
1203 return std::make_unique<MultisigDescriptor>((
int)data[0][0],
1214 return std::make_unique<SHDescriptor>(std::move(sub));
1222 return std::make_unique<AddressDescriptor>(std::move(dest));
1226 return std::make_unique<RawDescriptor>(script);
1240 error =
"Multiple '#' symbols";
1244 error =
"Missing checksum";
1250 strprintf(
"Expected 8 character checksum, not %u characters",
1257 error =
"Invalid characters in payload";
1264 "Provided checksum '%s' does not match computed checksum '%s'",
1277std::unique_ptr<Descriptor>
Parse(
const std::string &descriptor,
1285 if (
sp.size() == 0 &&
ret) {
1286 return std::unique_ptr<Descriptor>(std::move(
ret));
1303 return InferScript(script, ParseScriptContext::TOP, provider);
1347const std::unordered_map<uint32_t, ExtPubKeyMap>
@ TOP
Top-level scriptPubKey.
std::string FormatHDKeypath(const std::vector< uint32_t > &path)
const CChainParams & Params()
Return the currently selected parameters.
An encapsulated secp256k1 private key.
bool IsValid() const
Check whether this private key is valid.
CPubKey GetPubKey() const
Compute the public key from a private key.
bool Derive(CKey &keyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode &cc) const
Derive BIP32 child 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)
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.
void CacheDerivedExtPubKey(uint32_t key_exp_pos, uint32_t der_index, const CExtPubKey &xpub)
Cache an xpub derived at an index.
void CacheParentExtPubKey(uint32_t key_exp_pos, const CExtPubKey &xpub)
Cache a parent 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)
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 GetPubKey(const CKeyID &address, CPubKey &pubkey) 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_IF_NOT_DEBUG Span< C > first(std::size_t count) const noexcept
const Config & GetConfig()
CScript ParseScript(const std::string &s)
std::unique_ptr< Descriptor > InferDescriptor(const CScript &script, const SigningProvider &provider)
Find a descriptor for the specified script, using information from provider where possible.
std::unique_ptr< Descriptor > Parse(const std::string &descriptor, FlatSigningProvider &out, std::string &error, bool require_checksum)
Parse a descriptor string.
bool CheckChecksum(Span< const char > &sp, bool require_checksum, std::string &error, std::string *out_checksum=nullptr)
Check a descriptor checksum, and update desc to be the checksum-less part.
std::string GetDescriptorChecksum(const std::string &descriptor)
Get the checksum for a descriptor.
std::unordered_map< uint32_t, CExtPubKey > ExtPubKeyMap
std::string EncodeDestination(const CTxDestination &dest, const Config &config)
std::string EncodeExtKey(const CExtKey &key)
CExtPubKey DecodeExtPubKey(const std::string &str)
std::string EncodeSecret(const CKey &key)
CTxDestination DecodeDestination(const std::string &addr, const CChainParams ¶ms)
CKey DecodeSecret(const std::string &str)
std::string EncodeExtPubKey(const CExtPubKey &key)
CExtKey DecodeExtKey(const std::string &str)
bool error(const char *fmt, const Args &...args)
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.
std::vector< T > Split(const Span< const char > &sp, char sep)
Split a string on every instance of sep, returning a vector.
bool Func(const std::string &str, Span< const char > &sp)
Parse a function call.
Implement std::hash so RCUPtr can be used as a key for maps or sets.
T GetRand(T nMax=std::numeric_limits< T >::max()) noexcept
Generate a uniform random integer of type T in the range [0..nMax) nMax defaults to std::numeric_limi...
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE
static std::string ToString(const CService &ip)
bool IsSolvable(const SigningProvider &provider, const CScript &script)
Check whether we know how to sign for an output like this, assuming we have all private keys.
static bool GetPubKey(const SigningProvider &provider, const SignatureData &sigdata, const CKeyID &address, CPubKey &pubkey)
const SigningProvider & DUMMY_SIGNING_PROVIDER
FlatSigningProvider Merge(const FlatSigningProvider &a, const FlatSigningProvider &b)
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.
TxoutType Solver(const CScript &scriptPubKey, std::vector< std::vector< uint8_t > > &vSolutionsRet)
Parse a scriptPubKey and identify script type for standard scripts.
CScript GetScriptForRawPubKey(const CPubKey &pubKey)
Generate a P2PK script for the given pubkey.
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 > CTxDestination
A txout script template with a specific destination.
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 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.
std::map< CKeyID, std::pair< CPubKey, KeyOriginInfo > > origins
std::map< CKeyID, CPubKey > pubkeys
std::map< CKeyID, CKey > keys
std::map< CScriptID, CScript > scripts
std::vector< uint32_t > path
uint8_t fingerprint[4]
First 32 bits of the Hash160 of the public key at the root of the path.
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
template std::vector< std::byte > ParseHex(std::string_view)
bool IsHex(std::string_view str)
Returns true if each character in str is a hex character, and has an even number of hex digits.
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.