DEV Community

David Adeyemi
David Adeyemi

Posted on

Output Descriptors in Bitcoin, What are they and why do we need them

Today we make another attempt to demystify a concept you'll come across when working with Bitcoin wallets, Output Descriptors, also known as Wallet Descriptors. Before we go into defining output descriptors, Let's talk about some concepts that will not only help you understand descriptors but also how the need for them arose.

HIERARCHICAL DETERMINISTIC(HD) WALLETS, DERIVATION PATHS

HD wallets utilize a singular seed to generate a continuous sequence of child keys. This key is known as the root seed. The child keys generated can be used to create multiple child addresses/child wallets linked together in a hierarchical manner i.e. parent key creates a child key. The child key creates it's own child key, a grandchild of the initial Parent key, etc. Each key can also have siblings, creating a tree-like hierarchy. Keys created can be encoded as an address where Bitcoin can be sent to and locked. Wallets that use Mnemonic keys operate on this principle.

While the root key/ root seed serves as the starting point from which all other child keys that hold funds can be generated, it is not the only information required to successfully back up/transfer a Bitcoin wallet/address. It is also important to know the Derivation Path of each key that holds funds in a wallet.

The derivation Path lets your Bitcoin node know the route that was taken when this key was generated. For instance, a seed can have 4 child keys, each child key having 3 child keys. The derivation path of the second grandchild key of the 3rd child key would be written as [2/1]. Key numbering indexes start from 0. keys can have much longer derivation paths, with a key having a derivation path of [1/0/1/4]. Without knowing the derivation Path of your keys, it is possible to lose some coins that are locked in certain paths. Your wallet software would have to result to randomly choosing derivation Paths and eventually giving up after continuous scanning.

Output Descriptors

Ouput Descriptors, As the name implies are actually precise Descriptors of Output scripts. They help to describe how Bitcoin addresses are derived/encoded from certain inputs Depending on the type of address that was created. By reading a descriptor, you can know the type of input that was used to generate an address, the type of address, and it's derivation Path. Output Descriptors provide a human-readable, or rather "Engineer readable" format for reading this info.

Descriptors are visible as fields in several commands such as listunspent and getaddressinfo

Structure of an Output Descriptor

We will examine the structure of an Output Descriptor gotten from calling Bitcoin core's getaddressinfo RPC on a specific address:

$ bitcoin-cli getaddressinfo ms7ruzvL4atCu77n47dStMb3of6iScS8kZ
{
"address": "ms7ruzvL4atCu77n47dStMb3of6iScS8kZ",
"scriptPubKey": "76a9147f437379bcc66c40745edc1891ea6b3830e1975d88ac",
"ismine": true,
"solvable": true,
"desc": "pkh([d6043800/0'/0'/18']03efdee34c0009fd175f3b20b5e5a5517fd5d16746f2e635b44617adafeaebc388)#4ahsl9pk",
"iswatchonly": false,
"isscript": false,
"iswitness": false,
"pubkey": "03efdee34c0009fd175f3b20b5e5a5517fd5d16746f2e635b44617adafeaebc388",
"iscompressed": true,
"ischange": false,
"timestamp": 1592335136,
"hdkeypath": "m/0'/0'/18'",
"hdseedid": "fdea8e2630f00d29a9d6ff2af7bf5b358d061078",
"hdmasterfingerprint": "d6043800",
"labels": [
""
]
}

The descriptor field is contained above in the desc field. The value of the desc field above is "pkh([d6043800/0'/0'/18']03efdee34c0009fd175f3b20b5e5a5517fd5d16746f2e635b44617adafeaebc388)#4ahsl9pk". Let's look at the breakdown of a descriptor below:

function([derivation-path]key)#checksum

  1. Function: The function is used to create an address from that key. The type of function used determines the type of address that would be created. A legacy P2PKH address would use the pkh function. A P2WSH SegWit address would use wsh and a P2WPKH address would use wpkh.

  2. Derivation Path: This describe what part of an HD wallet is being exported. In this case it's a seed with the fingerprint d6043800 and then the 18th child of the 0th child of the 0th child (0'/0'/18') of that seed. There may also be a further derivation after the key: function([derivation-path]key/more-derivation)#checksum
    NB: It's worth noting here that if you ever get a derivation path without a fingerprint, you can make it up. It's just that if there's an existing one, you should match it. This is because if you ever go back to the device that created the fingerprint, you'll need to have the same one.

  3. Key: This refers to the key or set of keys that the descriptor function encodes. Depending on the type of address being created and it's requirement, This could be something traditional like an
    extended private key, extended public key or it could just be a public key for an address as in this case, it could be a set of addresses for a multi-signature, or it could be something else. This is the core data: the function explains what to do with it.

  4. Checksum: Descriptors are meant to be human transferrable. This checksum makes sure you got it right, especially in the case where it is being transferred by hand.

CONCLUSION

We have briefly examined what descriptors are and how they fit into the mechanism of HD wallets. Descriptors provide a readable way to describe output scripts. Also they assist HD wallets in recovering wallet keys by providing adequate information about the output script in it's Data.

Related Links

https://sadeeqcode.medium.com/how-output-descriptors-enable-wallet-recovery-2484362856fa

https://github.com/BlockchainCommons/Learning-Bitcoin-from-the-Command-Line/blob/master/03_5_Understanding_the_Descriptor.md#understand-a-descriptor

Top comments (0)