Skip to content

Consider a compact PSBT based encoding for wallet descriptors #135

@seedhammer

Description

@seedhammer

Prompted by discussions at wizardsardine/liana#539, this is a sketch for a BIP proposal for serializing wallet descriptors. I raise it here for comments and because Blockchain Commons is a recognized standards body for Bitcoin specifications. If there's enough interest, it should be fleshed out and proposed as a BIP.

A Go implementation written from scratch is here: https://github.com/seedhammer/bip-serialized-descriptors

At the high level, this is a binary and compact serialization specification for the [wallet-policies] BIP.

  • Binary format, based on the [BIP174] PSBT format.
  • Descriptor is in text, as described in BIPs 380-386 (+389). Like the wallet-policies BIP, keys are always by indexed reference.
  • Key references uses the wallet-policies format @<key-index>.
  • Miniscript is trivially supported, except pk(NAME) expressions are replaced with key indexes.

Borrowing from BIP174, the format would be

 <desc> := <magic> <global-map> <key-map>*
 <magic> := 0x64 0x65 0x73 0x63 0xFF
 <global-map> := <keypair>* 0x00
 <key-map> := <keypair>* 0x00
 <keypair> := <key> <value>
 <key> := <keylen> <keytype> <keydata>
 <value> := <valuelen> <valuedata>

Where <global-map> contains one or more of the fields:

  • DESC_BIP38x_DESCRIPTOR: The descriptor itself, encoded in UTF-8 according to the BIP380 family, with the Miniscript extensions. Keys must be specified as @ according to the wallet-policies BIP. Inline keys are not allowed.
  • DESC_NAME: The name of the wallet in UTF-8.
  • DESC_BIRTHDATE: The wallet birthdate in blocks, encoded as a compact integer.

In future, other script formats (Simplicity?) can be added as separate field types.

The <key-map> is a list of keys, matching the indexed references from the descriptor. Each <key-map> contains one or more of the fields:

  • PSBT_GLOBAL_XPUB: An extended key, encoded just like PSBTs would.
  • DESC_KEY_NAME: The name of the key encoded in UTF-8.

FAQ

Why not use the Blockchain Commons [BCR-2020-010] format?

The format was recently deprecated, for good reasons: its binary format is compact but difficult to extend to support extensions to the descriptor format, such as Miniscript.

Why not use the Blockchain Commons Envelope format for descriptors?

  • It relies on the CBOR encoding which is a significant complexity in a specification (more on CBOR later).
  • CBOR is more compact than text, but descriptors are encoded in text and does not enjoy any of the advantages of CBOR.

The standard is being developed and as such does not have an advantage of existing use.

Why not use CBOR for encoding?

  • CBOR is significantly more general, and therefore complex, than the PSBT encoding.
  • CBOR is more complex and thus require more code space, which is scarce in embedded applications.
  • Wallet software already include PSBT decoders for transaction processing. To be fair, most wallet software also includes some CBOR capability because of the Blockchain Commons UR standard (more on UR later).
  • A specification (or BIP) should ideally be complete and self-contained, and referencing another standard (CBOR) makes implementing, debugging and ensuring interoperability harder. For an example of this complexity, CBOR is not deterministic (I believe the Blockchain Commons is working on a dCBOR proposal to fix that).
  • The PSBT format is already a BIP and widely accepted. A self-contained specification based on an already widely accepted binary format increases our chances of widespread support. In particular, I'd like to see Bitcoin Core support this format.

What about QR code representation?

A straightforward encoding would be the use the Blockchain Commons [BCR-2020-005] standard for splitting the serialized descriptor into multiple QR code frames. I believe the general purpose bytes urtype is sufficient, because the magic header decreases the likelihood of misinterpretation.

Doesn't UR support rely on a CBOR implementation anyway?

It's true that the UR specification rely on CBOR for encoding data shards, but it's my understanding that the subset of CBOR required can practically be implemented ad-hoc without a full fledged CBOR library.

Some devices, such as the camera-less Coldcards, won't implement the UR encoding because they exchange serialized descriptors through higher bandwidth mediums such as SD cards, USB, or NFC.

Why not encode the descriptor itself in binary?

The BC envelope format made the same decision of encoding the descriptor in text, for good reasons:

  • The descriptor language is complicated and expanding. Relying on existing standards for encoding saves a lot of complexity and duplicate specification efforts. In particular, any future descriptor extension BIPs such as Miniscript may be used immediately for this BIP, without deciding on a binary representation first.
  • The major source of bloat, extended keys, are binary encoded for compactness and can be re-used multiple times in a single descriptor.

[wallet-policies] https://github.com/bitcoin/bips/blob/bb98f8017a883262e03127ab718514abf4a5e5f9/bip-wallet-policies.mediawiki
[BIP174] https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki
[BCR-2020-010] https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2020-010-output-desc.md
[BCR-2020-005] https://github.com/BlockchainCommons/Research/blob/master/papers/bcr-2020-005-ur.md

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions