2021-12-30 19:36:57 +02:00
// Copyright (c) 2018-2021 The Bitcoin Core developers
2018-07-04 18:08:19 -07:00
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
# ifndef BITCOIN_SCRIPT_DESCRIPTOR_H
# define BITCOIN_SCRIPT_DESCRIPTOR_H
2020-01-30 19:03:54 -05:00
# include <outputtype.h>
2018-07-04 18:08:19 -07:00
# include <script/script.h>
# include <script/sign.h>
2019-06-06 22:52:24 +02:00
# include <script/signingprovider.h>
2018-07-04 18:08:19 -07:00
2021-03-15 11:59:05 +08:00
# include <optional>
2018-07-04 18:08:19 -07:00
# include <vector>
2020-02-24 15:09:15 -05:00
using ExtPubKeyMap = std : : unordered_map < uint32_t , CExtPubKey > ;
/** Cache for single descriptor's derived extended pubkeys */
class DescriptorCache {
private :
/** Map key expression index -> map of (key derivation index -> xpub) */
std : : unordered_map < uint32_t , ExtPubKeyMap > m_derived_xpubs ;
/** Map key expression index -> parent xpub */
ExtPubKeyMap m_parent_xpubs ;
2021-03-01 16:18:59 -05:00
/** Map key expression index -> last hardened xpub */
ExtPubKeyMap m_last_hardened_xpubs ;
2020-02-24 15:09:15 -05:00
public :
/** Cache a parent xpub
*
* @ param [ in ] key_exp_pos Position of the key expression within the descriptor
* @ param [ in ] xpub The CExtPubKey to cache
*/
void CacheParentExtPubKey ( uint32_t key_exp_pos , const CExtPubKey & xpub ) ;
/** Retrieve a cached parent xpub
*
* @ param [ in ] key_exp_pos Position of the key expression within the descriptor
* @ param [ in ] xpub The CExtPubKey to get from cache
*/
bool GetCachedParentExtPubKey ( uint32_t key_exp_pos , CExtPubKey & xpub ) const ;
/** Cache an xpub derived at an index
*
* @ param [ in ] key_exp_pos Position of the key expression within the descriptor
* @ param [ in ] der_index Derivation index of the xpub
* @ param [ in ] xpub The CExtPubKey to cache
*/
void CacheDerivedExtPubKey ( uint32_t key_exp_pos , uint32_t der_index , const CExtPubKey & xpub ) ;
/** Retrieve a cached xpub derived at an index
*
* @ param [ in ] key_exp_pos Position of the key expression within the descriptor
* @ param [ in ] der_index Derivation index of the xpub
* @ param [ in ] xpub The CExtPubKey to get from cache
*/
bool GetCachedDerivedExtPubKey ( uint32_t key_exp_pos , uint32_t der_index , CExtPubKey & xpub ) const ;
2021-03-01 16:18:59 -05:00
/** Cache a last hardened xpub
*
* @ param [ in ] key_exp_pos Position of the key expression within the descriptor
* @ param [ in ] xpub The CExtPubKey to cache
*/
void CacheLastHardenedExtPubKey ( uint32_t key_exp_pos , const CExtPubKey & xpub ) ;
/** Retrieve a cached last hardened xpub
*
* @ param [ in ] key_exp_pos Position of the key expression within the descriptor
* @ param [ in ] xpub The CExtPubKey to get from cache
*/
bool GetCachedLastHardenedExtPubKey ( uint32_t key_exp_pos , CExtPubKey & xpub ) const ;
2020-02-24 15:09:15 -05:00
/** Retrieve all cached parent xpubs */
const ExtPubKeyMap GetCachedParentExtPubKeys ( ) const ;
/** Retrieve all cached derived xpubs */
const std : : unordered_map < uint32_t , ExtPubKeyMap > GetCachedDerivedExtPubKeys ( ) const ;
2021-03-01 16:18:59 -05:00
/** Retrieve all cached last hardened xpubs */
const ExtPubKeyMap GetCachedLastHardenedExtPubKeys ( ) const ;
2021-04-22 13:12:33 -04:00
/** Combine another DescriptorCache into this one.
* Returns a cache containing the items from the other cache unknown to current cache
*/
DescriptorCache MergeAndDiff ( const DescriptorCache & other ) ;
2020-02-24 15:09:15 -05:00
} ;
2019-09-23 16:54:01 -04:00
/** \brief Interface for parsed descriptor objects.
*
* Descriptors are strings that describe a set of scriptPubKeys , together with
* all information necessary to solve them . By combining all information into
* one , they avoid the need to separately import keys and scripts .
*
* Descriptors may be ranged , which occurs when the public keys inside are
* specified in the form of HD chains ( xpubs ) .
*
* Descriptors always represent public information - public keys and scripts -
* but in cases where private keys need to be conveyed along with a descriptor ,
* they can be included inside by changing public keys to private keys ( WIF
* format ) , and changing xpubs by xprvs .
*
* Reference documentation about the descriptor language can be found in
* doc / descriptors . md .
*/
2018-07-04 18:08:19 -07:00
struct Descriptor {
virtual ~ Descriptor ( ) = default ;
/** Whether the expansion of this descriptor depends on the position. */
virtual bool IsRange ( ) const = 0 ;
2018-10-12 18:27:00 -07:00
/** Whether this descriptor has all information about signing ignoring lack of private keys.
* This is true for all descriptors except ones that use ` raw ` or ` addr ` constructions . */
virtual bool IsSolvable ( ) const = 0 ;
2018-07-04 18:08:19 -07:00
/** Convert the descriptor back to a string, undoing parsing. */
virtual std : : string ToString ( ) const = 0 ;
2019-07-10 17:21:19 -04:00
/** Whether this descriptor will return one scriptPubKey or multiple (aka is or is not combo) */
virtual bool IsSingleType ( ) const = 0 ;
2018-07-04 18:08:19 -07:00
/** Convert the descriptor to a private string. This fails if the provided provider does not have the relevant private keys. */
virtual bool ToPrivateString ( const SigningProvider & provider , std : : string & out ) const = 0 ;
2020-05-04 18:07:25 -04:00
/** 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. */
2021-03-01 14:48:59 -05:00
virtual bool ToNormalizedString ( const SigningProvider & provider , std : : string & out , const DescriptorCache * cache = nullptr ) const = 0 ;
2020-05-04 18:07:25 -04:00
2018-07-04 18:08:19 -07:00
/** Expand a descriptor at a specified position.
*
2020-01-16 18:23:35 -08:00
* @ param [ in ] pos The position at which to expand the descriptor . If IsRange ( ) is false , this is ignored .
* @ param [ in ] provider The provider to query for private keys in case of hardened derivation .
* @ param [ out ] output_scripts The expanded scriptPubKeys .
* @ param [ out ] out Scripts and public keys necessary for solving the expanded scriptPubKeys ( may be equal to ` provider ` ) .
2020-02-25 16:01:58 -05:00
* @ param [ out ] write_cache Cache data necessary to evaluate the descriptor at this point without access to private keys .
2018-07-04 18:08:19 -07:00
*/
2020-02-25 16:01:58 -05:00
virtual bool Expand ( int pos , const SigningProvider & provider , std : : vector < CScript > & output_scripts , FlatSigningProvider & out , DescriptorCache * write_cache = nullptr ) const = 0 ;
2018-11-02 19:19:39 -07:00
/** Expand a descriptor at a specified position using cached expansion data.
*
2020-01-16 18:23:35 -08:00
* @ param [ in ] pos The position at which to expand the descriptor . If IsRange ( ) is false , this is ignored .
2020-02-25 16:01:58 -05:00
* @ param [ in ] read_cache Cached expansion data .
2020-01-16 18:23:35 -08:00
* @ param [ out ] output_scripts The expanded scriptPubKeys .
* @ param [ out ] out Scripts and public keys necessary for solving the expanded scriptPubKeys ( may be equal to ` provider ` ) .
2018-11-02 19:19:39 -07:00
*/
2020-02-25 16:01:58 -05:00
virtual bool ExpandFromCache ( int pos , const DescriptorCache & read_cache , std : : vector < CScript > & output_scripts , FlatSigningProvider & out ) const = 0 ;
2018-12-19 15:54:40 +13:00
/** Expand the private key for a descriptor at a specified position, if possible.
*
2020-01-16 18:23:35 -08:00
* @ param [ in ] pos The position at which to expand the descriptor . If IsRange ( ) is false , this is ignored .
* @ param [ in ] provider The provider to query for the private keys .
* @ param [ out ] out Any private keys available for the specified ` pos ` .
2018-12-19 15:54:40 +13:00
*/
virtual void ExpandPrivate ( int pos , const SigningProvider & provider , FlatSigningProvider & out ) const = 0 ;
2020-01-30 19:03:54 -05:00
/** @return The OutputType of the scriptPubKey(s) produced by this descriptor. Or nullopt if indeterminate (multiple or none) */
2021-03-15 10:41:30 +08:00
virtual std : : optional < OutputType > GetOutputType ( ) const = 0 ;
2018-07-04 18:08:19 -07:00
} ;
2019-09-23 16:54:01 -04:00
/** Parse a `descriptor` string. Included private keys are put in `out`.
2019-02-06 18:08:21 -08:00
*
2019-09-23 16:54:01 -04:00
* If the descriptor has a checksum , it must be valid . If ` require_checksum `
2019-02-06 18:08:21 -08:00
* is set , the checksum is mandatory - otherwise it is optional .
*
* If a parse error occurs , or the checksum is missing / invalid , or anything
2019-09-23 16:54:01 -04:00
* else is wrong , ` nullptr ` is returned .
2019-02-06 18:08:21 -08:00
*/
2019-08-02 18:04:02 -04:00
std : : unique_ptr < Descriptor > Parse ( const std : : string & descriptor , FlatSigningProvider & out , std : : string & error , bool require_checksum = false ) ;
2018-07-04 18:08:19 -07:00
2019-09-23 16:54:01 -04:00
/** Get the checksum for a `descriptor`.
2019-05-08 14:03:29 -07:00
*
2019-09-23 16:54:01 -04:00
* - If it already has one , and it is correct , return the checksum in the input .
* - If it already has one that is wrong , return " " .
* - If it does not already have one , return the checksum that would need to be added .
2019-05-08 14:03:29 -07:00
*/
std : : string GetDescriptorChecksum ( const std : : string & descriptor ) ;
2019-09-23 16:54:01 -04:00
/** Find a descriptor for the specified `script`, using information from `provider` where possible.
2018-10-12 18:22:22 -07:00
*
* A non - ranged descriptor which only generates the specified script will be returned in all
* circumstances .
*
* For public keys with key origin information , this information will be preserved in the returned
* descriptor .
*
* - If all information for solving ` script ` is present in ` provider ` , a descriptor will be returned
2019-09-23 16:54:01 -04:00
* which is IsSolvable ( ) and encapsulates said information .
2018-10-12 18:22:22 -07:00
* - Failing that , if ` script ` corresponds to a known address type , an " addr() " descriptor will be
2019-09-23 16:54:01 -04:00
* returned ( which is not IsSolvable ( ) ) .
2018-10-12 18:22:22 -07:00
* - Failing that , a " raw() " descriptor is returned .
*/
std : : unique_ptr < Descriptor > InferDescriptor ( const CScript & script , const SigningProvider & provider ) ;
2018-07-04 18:08:19 -07:00
2018-10-12 18:22:22 -07:00
# endif // BITCOIN_SCRIPT_DESCRIPTOR_H