Introduction

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

  • Knowledge of what is needed to redeem funds attached to a transaction is clear and unambiguous so the structure and logic is more orderly
  • When importing keys into a wallet:
  • knowledge of which derivation path to use is unambiguous
  • knowledge of what type of address to produce is also unambiguous
  • Backups are extremely easy as they are simply terse strings

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

  • Interoperability between wallets is now easier to implement
  • Wallets are easier to update when new scripting structures and features are released
  • It is easier for wallets to be more expressive in the types of scripts they recognise

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 nameInput typeOutputExample
pkKeyscriptPubKeypk(0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798)#gn28ywm7​​
pkhKeyscriptPubKeypkh(02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5)#8fhd9pwu​
wpkhKeyscriptPubKeywpkh(02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9)#8zl0zxma
shScriptA script describing outputs with the input as embedded scriptsh(wpkh(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556)#8mwyhs2t​
wshScriptA script describing outputs with the input as embedded scriptwsh(multi(2,03a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7,03774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb,03d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a))#en3tu306​

Table-1

The rules describing inputs and outputs for a limited number of descriptor functions are summarised above. For full details, including multisig scripts please see https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md

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

Example-1

pkh(02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5)#8fhd9pwu

Let’s break this down

SectionDescription
pkhThis is the function name. In this example this descriptor creates P2PKH bitcoin addresses.
02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5This is the argument, which is the public key in hex format.
8fhd9pwuThis 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: https://iancoleman.io/bitcoin-key-compression/

Example 2

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

SectionDescription
pkhThis 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:https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki
xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcELThe 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 https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki
#ml40v0wf​checksum

Conclusion

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: https://www.youtube.com/watch?v=xC25NzIjzog&t=4s