Inside Bitcoin
Opening the selected file…
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1// Copyright (c) 2018-present The Bitcoin Core developers2// Distributed under the MIT software license, see the accompanying3// file COPYING or http://www.opensource.org/licenses/mit-license.php.5#ifndef BITCOIN_SCRIPT_DESCRIPTOR_H6#define BITCOIN_SCRIPT_DESCRIPTOR_H8#include <outputtype.h>9#include <pubkey.h>10#include <uint256.h>12#include <cstddef>13#include <cstdint>14#include <memory>15#include <optional>16#include <set>17#include <string>18#include <string_view>19#include <unordered_map>20#include <vector>22class CScript;23class SigningProvider;24struct FlatSigningProvider;26using ExtPubKeyMap = std::unordered_map<uint32_t, CExtPubKey>;28/** Cache for single descriptor's derived extended pubkeys */29class DescriptorCache {30private:31/** Map key expression index -> map of (key derivation index -> xpub) */32std::unordered_map<uint32_t, ExtPubKeyMap> m_derived_xpubs;33/** Map key expression index -> parent xpub */34ExtPubKeyMap m_parent_xpubs;35/** Map key expression index -> last hardened xpub */36ExtPubKeyMap m_last_hardened_xpubs;38public:39/** Cache a parent xpub40*41* @param[in] key_exp_pos Position of the key expression within the descriptor42* @param[in] xpub The CExtPubKey to cache43*/44void CacheParentExtPubKey(uint32_t key_exp_pos, const CExtPubKey& xpub);45/** Retrieve a cached parent xpub46*47* @param[in] key_exp_pos Position of the key expression within the descriptor48* @param[out] xpub The CExtPubKey to get from cache49*/50bool GetCachedParentExtPubKey(uint32_t key_exp_pos, CExtPubKey& xpub) const;51/** Cache an xpub derived at an index52*53* @param[in] key_exp_pos Position of the key expression within the descriptor54* @param[in] der_index Derivation index of the xpub55* @param[in] xpub The CExtPubKey to cache56*/57void CacheDerivedExtPubKey(uint32_t key_exp_pos, uint32_t der_index, const CExtPubKey& xpub);58/** Retrieve a cached xpub derived at an index59*60* @param[in] key_exp_pos Position of the key expression within the descriptor61* @param[in] der_index Derivation index of the xpub62* @param[out] xpub The CExtPubKey to get from cache63*/64bool GetCachedDerivedExtPubKey(uint32_t key_exp_pos, uint32_t der_index, CExtPubKey& xpub) const;65/** Cache a last hardened xpub66*67* @param[in] key_exp_pos Position of the key expression within the descriptor68* @param[in] xpub The CExtPubKey to cache69*/70void CacheLastHardenedExtPubKey(uint32_t key_exp_pos, const CExtPubKey& xpub);71/** Retrieve a cached last hardened xpub72*73* @param[in] key_exp_pos Position of the key expression within the descriptor74* @param[out] xpub The CExtPubKey to get from cache75*/76bool GetCachedLastHardenedExtPubKey(uint32_t key_exp_pos, CExtPubKey& xpub) const;78/** Retrieve all cached parent xpubs */79ExtPubKeyMap GetCachedParentExtPubKeys() const;80/** Retrieve all cached derived xpubs */81std::unordered_map<uint32_t, ExtPubKeyMap> GetCachedDerivedExtPubKeys() const;82/** Retrieve all cached last hardened xpubs */83ExtPubKeyMap GetCachedLastHardenedExtPubKeys() const;85/** Combine another DescriptorCache into this one.86* Returns a cache containing the items from the other cache unknown to current cache87*/88DescriptorCache MergeAndDiff(const DescriptorCache& other);89};91/** \brief Interface for parsed descriptor objects.92*93* Descriptors are strings that describe a set of scriptPubKeys, together with94* all information necessary to solve them. By combining all information into95* one, they avoid the need to separately import keys and scripts.96*97* Descriptors may be ranged, which occurs when the public keys inside are98* specified in the form of HD chains (xpubs).99*100* Descriptors always represent public information - public keys and scripts -101* but in cases where private keys need to be conveyed along with a descriptor,102* they can be included inside by changing public keys to private keys (WIF103* format), and changing xpubs by xprvs.104*105* Reference documentation about the descriptor language can be found in106* doc/descriptors.md.107*/108struct Descriptor {109virtual ~Descriptor() = default;111/** Whether the expansion of this descriptor depends on the position. */112virtual bool IsRange() const = 0;114/** Whether this descriptor has all information about signing ignoring lack of private keys.115* This is true for all descriptors except ones that use `raw` or `addr` constructions. */116virtual bool IsSolvable() const = 0;118/** Convert the descriptor back to a string, undoing parsing. */119virtual std::string ToString(bool compat_format=false) const = 0;121/** Convert the descriptor to the canonical string.122* The canonical string is the same as the public string but always uses h as the hardened indicator123*/124virtual std::string ToCanonicalString() const = 0;126/** Whether this descriptor will return at most one scriptPubKey or multiple (aka is or is not combo) */127virtual bool IsSingleType() const = 0;129/** Whether the given provider has all private keys required by this descriptor.130* @return `false` if the descriptor doesn't have any keys or subdescriptors,131* or if the provider does not have all private keys required by132* the descriptor.133*/134virtual bool HavePrivateKeys(const SigningProvider& provider) const = 0;136/** Convert the descriptor to a private string. This uses public keys if the relevant private keys are not in the SigningProvider.137* If none of the relevant private keys are available, the output string in the "out" parameter will not contain any private key information,138* and this function will return "false".139* @param[in] provider The SigningProvider to query for private keys.140* @param[out] out The resulting descriptor string, containing private keys if available.141* @returns true if at least one private key available.142*/143virtual bool ToPrivateString(const SigningProvider& provider, std::string& out) const = 0;145/** Convert the descriptor to a normalized string. Normalized descriptors have the xpub at the last hardened step. This fails if the provided provider does not have the private keys to derive that xpub. */146virtual bool ToNormalizedString(const SigningProvider& provider, std::string& out, const DescriptorCache* cache = nullptr) const = 0;148/** Whether the descriptor can be used to produce its address(es) without needing a cache or private keys. */149virtual bool CanSelfExpand() const = 0;151/** Expand a descriptor at a specified position.152*153* @param[in] pos The position at which to expand the descriptor. If IsRange() is false, this is ignored.154* @param[in] provider The provider to query for private keys in case of hardened derivation.155* @param[out] output_scripts The expanded scriptPubKeys.156* @param[out] out Scripts and public keys necessary for solving the expanded scriptPubKeys (may be equal to `provider`).157* @param[out] write_cache Cache data necessary to evaluate the descriptor at this point without access to private keys.158*/159virtual bool Expand(int pos, const SigningProvider& provider, std::vector<CScript>& output_scripts, FlatSigningProvider& out, DescriptorCache* write_cache = nullptr) const = 0;161/** Expand a descriptor at a specified position using cached expansion data.162*163* @param[in] pos The position at which to expand the descriptor. If IsRange() is false, this is ignored.164* @param[in] read_cache Cached expansion data.165* @param[out] output_scripts The expanded scriptPubKeys.166* @param[out] out Scripts and public keys necessary for solving the expanded scriptPubKeys (may be equal to `provider`).167*/168virtual bool ExpandFromCache(int pos, const DescriptorCache& read_cache, std::vector<CScript>& output_scripts, FlatSigningProvider& out) const = 0;170/** Expand the private key for a descriptor at a specified position, if possible.171*172* @param[in] pos The position at which to expand the descriptor. If IsRange() is false, this is ignored.173* @param[in] provider The provider to query for the private keys.174* @param[out] out Any private keys available for the specified `pos`.175*/176virtual void ExpandPrivate(int pos, const SigningProvider& provider, FlatSigningProvider& out) const = 0;178/** @return The OutputType of the scriptPubKey(s) produced by this descriptor. Or nullopt if indeterminate (multiple or none) */179virtual std::optional<OutputType> GetOutputType() const = 0;181/** Get the size of the scriptPubKey for this descriptor. */182virtual std::optional<int64_t> ScriptSize() const = 0;184/** Get the maximum size of a satisfaction for this descriptor, in weight units.185*186* @param use_max_sig Whether to assume ECDSA signatures will have a high-r.187*/188virtual std::optional<int64_t> MaxSatisfactionWeight(bool use_max_sig) const = 0;190/** Get the maximum size number of stack elements for satisfying this descriptor. */191virtual std::optional<int64_t> MaxSatisfactionElems() const = 0;193/** Return all (extended) public keys for this descriptor, including any from subdescriptors.194*195* @param[out] pubkeys Any public keys196* @param[out] ext_pubs Any extended public keys197*/198virtual void GetPubKeys(std::set<CPubKey>& pubkeys, std::set<CExtPubKey>& ext_pubs) const = 0;200/** Whether this descriptor produces any scripts with the Expand functions */201virtual bool HasScripts() const = 0;203/** Semantic/safety warnings (includes subdescriptors). */204virtual std::vector<std::string> Warnings() const = 0;206/** Get the maximum key expression index. Used only for tests */207virtual uint32_t GetMaxKeyExpr() const = 0;209/** Get the number of key expressions in this descriptor. Used only for tests */210virtual size_t GetKeyCount() const = 0;211};213/** Parse a `descriptor` string. Included private keys are put in `out`.214*215* If the descriptor has a checksum, it must be valid. If `require_checksum`216* is set, the checksum is mandatory - otherwise it is optional.217*218* If a parse error occurs, or the checksum is missing/invalid, or anything219* else is wrong, an empty vector is returned.220*/221std::vector<std::unique_ptr<Descriptor>> Parse(std::string_view descriptor, FlatSigningProvider& out, std::string& error, bool require_checksum = false);223/** Get the checksum for a `descriptor`.224*225* - If it already has one, and it is correct, return the checksum in the input.226* - If it already has one that is wrong, return "".227* - If it does not already have one, return the checksum that would need to be added.228*/229std::string GetDescriptorChecksum(const std::string& descriptor);231/** Find a descriptor for the specified `script`, using information from `provider` where possible.232*233* A non-ranged descriptor which only generates the specified script will be returned in all234* circumstances.235*236* For public keys with key origin information, this information will be preserved in the returned237* descriptor.238*239* - If all information for solving `script` is present in `provider`, a descriptor will be returned240* which is IsSolvable() and encapsulates said information.241* - Failing that, if `script` corresponds to a known address type, an "addr()" descriptor will be242* returned (which is not IsSolvable()).243* - Failing that, a "raw()" descriptor is returned.244*/245std::unique_ptr<Descriptor> InferDescriptor(const CScript& script, const SigningProvider& provider);247/** Hash of the COMPAT string representation of the descriptor that is not supposed to change over time.248* Due to the hash's usage in previous versions, the COMPAT string is computed with some quirks.249*250* The hash is the sha256 of the public descriptor using apostrophes as the hardened indicator, except inside of
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.