Rethinking Wallet Architecture using Wallet Descriptors

Last updated June 22, 2020, 8:27 a.m. | Posted by Leon Johnson


Bitcoin Core’s wallet recently changed. At the Advancing Bitcoin Conference 2020, Andrew Chow spoke about Rethinking Wallet Architecture. Previously, the wallet inside of Bitcoin Core (the CWallet class) followed a ‘bunch of keys’ model. It was an unstructured collection of keys, scripts, watch scripts, keypools, HD chains, and metadata.

Explaining descriptors

If we delve a bit deeper, the bunch of keys model has a number of problems with it:

  1. Given a key, it is not clear what pieces of the puzzle are needed to access the funds ( solve the scriptsig)
  2. Using the current model, it is difficult to expand what is possible, both now and in the future when new features are introduced
    • Multisig
    • An unusual contract
    • BIP 124 type contracts

This issue was first documented by Pieter Wuille in 2017 and it’s interesting to see the progression of this issue into the solution now implemented. An elegant solution to this problem was to redesign Bitcoin Core’s wallet architecture to use Descriptors. In simple terms, a descriptor is information that describes data. You can find descriptors in your favorite programming language and application frameworks, they are commonly used across computing.

Bitcoin Core’s wallet architecture previously focused on taking a key, applying a script to it, and presenting it to the user. The new architecture now focused on structuring everything around descriptors to describe all of the information needed to solve the scriptsig, and ultimately claim the funds.

Benefits of this solution

The benefits aren’t only for Core. Wallet developers can also take note and implement descriptors into their wallet. Benefits of this include:

Descriptors in details

Native wallet descriptors (in Core) are ‘engineer readable’  so anyone with a good understanding of bitcoin code can understand at a high level what is needed. Below we discuss this in a bit more detail.

In Core, a descriptor is simply a function with the following attributes:

Function name Input type Output Example
pk Key scriptPubKey pk(0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798)#gn28ywm7​​
pkh Key scriptPubKey pkh(02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5)#8fhd9pwu​
wpkh Key scriptPubKey wpkh(02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9)#8zl0zxma
sh Script A script describing outputs with the input as embedded script sh(wpkh(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556)#8mwyhs2t​
wsh Script A script describing outputs with the input as embedded script wsh(multi(2,03a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7,03774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb,03d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a))#en3tu306​


The rules describing inputs and outputs for a limited number of descriptor functions are summarised above. For full details, including multisig scripts please see

Structure of a descriptor function

A descriptor returns a script.

Some have a checksum at the end after hash.

We can demonstrate the structure of a descriptor in pseudo code as:

descriptor_name(argument) => script



Let’s break this down

Section Description
pkh This is the function name. In this example this descriptor creates P2PKH bitcoin addresses.
02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5 This is the argument, which is the public key in hex format.
8fhd9pwu This is a checksum that bitcoin wallets can use to check whether the public key provided as an input is a valid public key.

If we then encode the pubkey above 02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5 we get the bitcoin address: 1cMh228HTCiwS8ZsaakH8A8wze1JR5ZsP

Give it a try here:

Example 2

pkh([d34db33f/44'/0'/0'] xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/*)#ml40v0wf​

Section Description
pkh This is the function name. In this example this descriptor creates P2PKH bitcoin addresses.
[d34db33f/44'/0'/0'] This is key origin information, which is made up of the fingerprint and the derivation path. This tells us that this pubkey (xpub) is derived from the master key with fingerprint d34db33f and a derivation path of 44'/0'/0'. For more information on BIP-32 derivation paths please see:
xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL The xpub.
/1/* Range descriptor. This tells the wallet where to find more keys at. This is a BIP 44 style derivation path. For more info please see
#ml40v0wf​ checksum


Native wallet descriptors will be implemented into Core shortly and hopefully other bitcoin wallets will implement descriptors which provides us with better bitcoin wallet interoperability.

You can watch Andrew Chow speak about Rethinking Wallet Architecture here: 

Thanks for reading!

If you enjoyed it, please share it on Twitter.