Files
bips/bip-0139/field-registry.md
T
pythcoiner 100ba872c8 Add BIP139: Wallet Metadata Backup Format (#2130)
* bip139: wallet metadata format

* bip139: add the Version header to the preamble

* bip139: keep a single psbts field and fix the spend status link

* bip139: fold the version section and bip field into the version value

* bip139: capitalize Bitcoin Core and clarify the change_descriptor note

* bip139: replace the three account birth time fields with birth_block

* bip139: drop descriptor_id and change_descriptor_id

* bip139: drop field aliases, keeping name and labels

* bip139: restrict descriptor and change_descriptor to a string

* bip139: make version, type, descriptor, key, txid, outpoint and tweak mandatory

* bip139: move field definitions to a companion registry

* bip139: add the wallet survey behind these decisions

* bip139: replace the wallet description field with a backup note

* bip139: add the backup date field

* bip139: add the account gap_limit field

* bip139: add the multi_bip380 account type

* bip139: give the bip352_labels range an explicit encoding

* bip139: add a general coin object

* bip139: move signers above the account

* bip139: add signer modality and device records

* bip139: add bip85 application and index

* bip139: add Bitkey to the wallet survey

* bip139: state how to derive birth_block from a creation date

* bip139: define the timestamp format once

* bip139: rename the transaction time field to block_time

* bip139: keep last_height on the account only

* bip139: state that type names the descriptor language

* bip139: drop output_type, the descriptor already states it

* bip139: replace the account active flag with a status enum

* bip139: add mutinynet and scope a backup to one network

* bip139: record that the label gap belongs to BIP-329

* bip139: record that proprietary needs no change

* bip139: make the survey annex-ready

* bip139: record that mainnet mnemonics stay out of scope

* bip139: reword the mnemonic evidence heading

* bip139: correct the birth_block evidence, Sparrow stores a height

* bip139: type and descriptor fit every surveyed wallet

* bip139: correct the addr descriptor solvability note

* bip139: re-assess every partial score against fillability

* bip139: store psbts once at wallet level, reference them per account

* bip139: store transactions once at wallet level, reference them per account

* bip139: txid is the transaction map key, not a field

* bip139: refresh the matrix after the fillability re-assessment

* bip139: electrum holds no bip39 mnemonic at all

* bip139: sp_output.label has no constituency

* bip139: collapse the survey to a two-value scale

* bip139: drop the obsolete partial-score analysis

* bip139: size the matrix field column from the data

* bip139: cut the survey down to the table and its results

* bip139: recompute liana compat against the current draft

* bip139: correct the liana breaking-change count

* bip139: make network mandatory

* bip139: network no longer breaks liana on import

* bip139: render wallet fields as a wrapped table

* bip139: render account fields as a wrapped table

* bip139: render every field section as a wrapped table

* bip139: the registry is part of the bip, not a reference to it

* bip139: drop the registration process from the registry intro

* bip139: put field rationale in the cell, not below the table

* bip139: keep code spans whole when wrapping cells

* bip139: render field tables as preformatted blocks

* bip139: drop link definitions the tables no longer use

* bip139: use a bordered grid for the field tables

* bip139: give birth_block an estimation formula and drop the enum underscore

* bip139: merge silent payment outputs into the coin object

* bip139: restore spend_status and give the sp label scalar a home

* bip139: register the transaction fee field

* bip139: rebuild the survey matrix against the current field set

* bip139: drop survey findings the draft now addresses

* bip139: bar passphrase-protected seeds from bip39_mnemonic

* bip139: record the missing-field decisions in the survey

* bip139: cut the survey down to its revision list and matrix

* bip139: reword the survey as a wallet to field mapping

* bip139: reference the wallet support annex from the spec

* bip139: list the mandatory fields in the registry tables

* bip139: point the spec at the registry as the complete field list

* bip139: spell out mandatory and optional in the registry req column

* bip139: mark only the optional fields in the registry tables

* bip139: retitle and reframe the BIP around moving between wallets

* bip139: call the artefact an export throughout

* bip139: scope the mnemonic advice to exports kept as backups

* bip139: say that most metadata cannot be recovered from the chain

* bip139: clarify account and signer metadata fields

* bip139: cut the registry cells back to the field description

* bip139: reword the registry field descriptions

* bip139: give the device record its own registry table

* bip139: keep an unknown enum value from failing the import

* bip139: define the device transports field

* bip139: point the devices row at the device object

* bip139: backup -> export in README

* bip139: clarify export fields and remove survey annex

* bip139: Drop Version header in absence of Changelog
2026-10-24 08:11:13 -07:00

28 KiB

BIP-0139 Field Registry

This file is the central repository of fields for the BIP-0139 wallet metadata export format.
The optional column marks the optional fields, a blank means the field is mandatory. Mandatory fields are fixed by BIP-0139, so a pull request against this file may add or change optional fields only.

Wallet Fields

Fields of the top-level wallet object.

| field        | optional | type      | description                                                |
|--------------|----------|-----------|------------------------------------------------------------|
| version      |          | string    | Export format and version. See Wallet Object Structure for |
|              |          |           | the required value.                                        |
|--------------|----------|-----------|------------------------------------------------------------|
| network      |          | string    | Network of the wallet. See Wallet Object Structure for the |
|              |          |           | permitted values.                                          |
|--------------|----------|-----------|------------------------------------------------------------|
| accounts     |          | array     | Account objects. Must not be empty.                        |
|--------------|----------|-----------|------------------------------------------------------------|
| name         | optional | string    | Wallet name or alias.                                      |
|--------------|----------|-----------|------------------------------------------------------------|
| note         | optional | string    | Note about this export, written by the user when the       |
|              |          |           | export is made.                                            |
|--------------|----------|-----------|------------------------------------------------------------|
| date         | optional | timestamp | When the export was made.                                  |
|--------------|----------|-----------|------------------------------------------------------------|
| exporter     | optional | string    | Name and version of the software that produced this        |
|              |          |           | export, e.g. `Sparrow 2.2.0`.                              |
|--------------|----------|-----------|------------------------------------------------------------|
| transactions | optional | object    | Maps a transaction id to a transaction object.             |
|              |          |           | Transactions are recorded here rather than in the          |
|              |          |           | `account` object so a transaction related to several       |
|              |          |           | accounts is stored only once. Accounts reference them by   |
|              |          |           | transaction id.                                            |
|--------------|----------|-----------|------------------------------------------------------------|
| psbts        | optional | object    | Maps a transaction id to a PSBT, as defined by BIP-0174 or |
|              |          |           | BIP-0370. The key is the transaction id of the PSBT's      |
|              |          |           | *unsigned* transaction, which stays stable for the whole   |
|              |          |           | signing process, whereas the id of the finalized           |
|              |          |           | transaction changes as legacy inputs are signed. Kept at   |
|              |          |           | wallet level for the same reason as transactions.          |
|--------------|----------|-----------|------------------------------------------------------------|
| signers      | optional | array     | Signer objects.                                            |
|--------------|----------|-----------|------------------------------------------------------------|
| proprietary  | optional | object    | Application-specific metadata.                             |

Account Fields

Fields of the account object.

| field              | optional | type            | description                                    |
|--------------------|----------|-----------------|------------------------------------------------|
| type               |          | string          | Type of account descriptor. See Account Object |
|                    |          |                 | Structure for the permitted values.            |
|--------------------|----------|-----------------|------------------------------------------------|
| descriptor         |          | string/array    | Account descriptor. Its structure is defined   |
|                    |          |                 | by `type`. See Account Object Structure.       |
|--------------------|----------|-----------------|------------------------------------------------|
| name               | optional | string          | Account name/alias.                            |
|--------------------|----------|-----------------|------------------------------------------------|
| description        | optional | string          | Account description.                           |
|--------------------|----------|-----------------|------------------------------------------------|
| status             | optional | enum            | Where the account is in its lifecycle. See     |
|                    |          |                 | Account Status.                                |
|--------------------|----------|-----------------|------------------------------------------------|
| hidden             | optional | boolean         | Whether the account is hidden in the wallet's  |
|                    |          |                 | interface. Independent of status: a hidden     |
|                    |          |                 | account may still be active.                   |
|--------------------|----------|-----------------|------------------------------------------------|
| change_descriptor  | optional | string          | Explicit change-side descriptor, paired with   |
|                    |          |                 | descriptor. For wallets that keep receive and  |
|                    |          |                 | change descriptors separate, such as Bitcoin   |
|                    |          |                 | Core.                                          |
|--------------------|----------|-----------------|------------------------------------------------|
| receive_index      | optional | integer         | Maximum generated receive index for receive    |
|                    |          |                 | addresses.                                     |
|--------------------|----------|-----------------|------------------------------------------------|
| change_index       | optional | integer         | Maximum generated change index for change      |
|                    |          |                 | addresses.                                     |
|--------------------|----------|-----------------|------------------------------------------------|
| range_start        | optional | integer         | Cached keypool range start of the receive      |
|                    |          |                 | descriptor. Ranged descriptors only.           |
|--------------------|----------|-----------------|------------------------------------------------|
| range_end          | optional | integer         | Cached keypool range end of the receive        |
|                    |          |                 | descriptor. Ranged descriptors only.           |
|--------------------|----------|-----------------|------------------------------------------------|
| change_range_start | optional | integer         | Cached keypool range start of the              |
|                    |          |                 | change_descriptor. Ranged descriptors only.    |
|--------------------|----------|-----------------|------------------------------------------------|
| change_range_end   | optional | integer         | Cached keypool range end of the                |
|                    |          |                 | change_descriptor. Ranged descriptors only.    |
|--------------------|----------|-----------------|------------------------------------------------|
| gap_limit          | optional | integer         | Consecutive unused addresses a wallet must     |
|                    |          |                 | scan past the last used one before concluding  |
|                    |          |                 | there are no more. A single value covers both  |
|                    |          |                 | the receive and change sides.                  |
|--------------------|----------|-----------------|------------------------------------------------|
| birth_block        | optional | integer         | Account creation time as a block height. An    |
|                    |          |                 | importer may start scanning here instead of at |
|                    |          |                 | genesis. Many wallets record a creation date   |
|                    |          |                 | rather than a block height. An exporter        |
|                    |          |                 | holding only a date SHOULD convert it against  |
|                    |          |                 | a chain source. If it cannot, it MAY estimate  |
|                    |          |                 | the height as (date - genesis_block_time) /    |
|                    |          |                 | 600, anchored at the network's genesis block   |
|                    |          |                 | and never at the chain tip: the chain has      |
|                    |          |                 | historically run slightly ahead of the         |
|                    |          |                 | ten-minute target, so extrapolating forward    |
|                    |          |                 | from genesis should land below the true height |
|                    |          |                 | while counting back from the tip lands above   |
|                    |          |                 | it. The estimate MUST be at or before the true |
|                    |          |                 | height, never after, because too early only    |
|                    |          |                 | costs scanning time while too late silently    |
|                    |          |                 | misses transactions. An exporter that can do   |
|                    |          |                 | neither SHOULD omit this field.                |
|--------------------|----------|-----------------|------------------------------------------------|
| last_height        | optional | integer         | Height this account has been synced to. A      |
|                    |          |                 | wallet that tracks one sync point for the      |
|                    |          |                 | whole export writes that same height into      |
|                    |          |                 | every account.                                 |
|--------------------|----------|-----------------|------------------------------------------------|
| bip352_labels      | optional | array or object | The silent payment label indices in use.       |
|                    |          |                 | Either an array of integers ([0, 1, 2]) or an  |
|                    |          |                 | object with start and end members ({"start":   |
|                    |          |                 | 0, "end": 10}), where end is exclusive.        |
|--------------------|----------|-----------------|------------------------------------------------|
| keys               | optional | object          | Maps a key fingerprint to a key object.        |
|--------------------|----------|-----------------|------------------------------------------------|
| labels             | optional | array           | Label structures for transactions, addresses,  |
|                    |          |                 | outputs and keys, following BIP-0329.          |
|--------------------|----------|-----------------|------------------------------------------------|
| transactions       | optional | array           | Transaction ids referencing the wallet's       |
|                    |          |                 | transactions map, for transactions related to  |
|                    |          |                 | this account.                                  |
|--------------------|----------|-----------------|------------------------------------------------|
| coins              | optional | array           | Coin objects owned by the account, silent      |
|                    |          |                 | payment outputs included.                      |
|--------------------|----------|-----------------|------------------------------------------------|
| psbts              | optional | array           | Transaction ids referencing the wallet's psbts |
|                    |          |                 | map, for PSBTs related to this account.        |
|--------------------|----------|-----------------|------------------------------------------------|
| bip39_mnemonic     | optional | string          | Mnemonic words following BIP-0039. Since       |
|                    |          |                 | exports may be stored online, this field is    |
|                    |          |                 | intended for test networks only (testnet3,     |
|                    |          |                 | testnet4, signet, regtest); it MUST NOT be     |
|                    |          |                 | used to store mainnet mnemonics. The field     |
|                    |          |                 | carries the words alone. A seed protected by a |
|                    |          |                 | BIP-39 passphrase MUST NOT use it.             |
|--------------------|----------|-----------------|------------------------------------------------|
| proprietary        | optional | object          | Application-specific metadata.                 |

Account Status

The status field may contain one of the following values.

  • active: The account can derive new addresses.
  • superseded: The account no longer derives new addresses, but must still be watched because it may hold or receive coins.
  • archived: The user retired the account, it is no longer watched.

Signer Fields

Fields of the signer object.

| field                 | optional | type    | description                                         |
|-----------------------|----------|---------|-----------------------------------------------------|
| fingerprints          |          | array   | BIP32 fingerprints of keys held by this signer.     |
|-----------------------|----------|---------|-----------------------------------------------------|
| key_status            | optional | enum    | Status of the signer's keys. See Key Status.        |
|-----------------------|----------|---------|-----------------------------------------------------|
| bip85_derivation_path | optional | string  | BIP-0085 derivation path used to derive this        |
|                       |          |         | signer's key from a master key, if one was used.    |
|-----------------------|----------|---------|-----------------------------------------------------|
| key_storage           | optional | enum    | Whether the signer's key is `hot` or `cold`.        |
|-----------------------|----------|---------|-----------------------------------------------------|
| devices               | optional | array   | Device objects for the last-seen devices holding    |
|                       |          |         | this key. Entries are not keyed and do not identify |
|                       |          |         | a physical device across exports. See Device       |
|                       |          |         | object.                                             |

Key Status

The key_status field may contain one of the following values.

  • inactive: The key is not yet actively used.
  • active: The key is actively used.
  • revoked: The key has been revoked and MUST NOT be used anymore.

Device object

The device object may contain any of these fields.

| field               | optional | type      | description                                        |
|---------------------|----------|-----------|----------------------------------------------------|
| vendor              | optional | string    | Device vendor name.                                |
|---------------------|----------|-----------|----------------------------------------------------|
| model               | optional | string    | Device model name.                                 |
|---------------------|----------|-----------|----------------------------------------------------|
| firmware_version    | optional | string    | Device firmware version. See Device Firmware       |
|                     |          |           | Version.                                           |
|---------------------|----------|-----------|----------------------------------------------------|
| transports          | optional | array     | Media over which the device can be reached, in     |
|                     |          |           | order of preference. See Device Transports.        |
|---------------------|----------|-----------|----------------------------------------------------|
| registered          | optional | bool      | Whether the descriptor has been registered on the  |
|                     |          |           | device.                                            |
|---------------------|----------|-----------|----------------------------------------------------|
| descriptor_checksum | optional | string    | Checksum of the descriptor that registered applies |
|                     |          |           | to. Devices are listed at wallet level, a          |
|                     |          |           | registration covers a single descriptor. An        |
|                     |          |           | importer MUST treat registered as absent when this |
|                     |          |           | does not match the descriptor being imported.      |
|---------------------|----------|-----------|----------------------------------------------------|
| descriptor_stored   | optional | bool      | Whether the device kept the descriptor, so later   |
|                     |          |           | requests may name it by its alias alone.           |
|                     |          |           | Independent of proof of registration: a device     |
|                     |          |           | may store the descriptor and return a proof.       |
|---------------------|----------|-----------|----------------------------------------------------|
| last_health_check   | optional | timestamp | Timestamp of the last health check processed on    |
|                     |          |           | this device.                                       |

Device Transports

The transports array may contain any of the following values.

  • usb: Wired connection, whether the device presents as an HID device or as a serial port.
  • bluetooth: Wireless connection to the host.
  • nfc: Tap, including devices presenting as a smartcard.
  • qr: QR codes, animated or not. The encoding is not recorded here.
  • sdcard: A file carried to the device on removable storage.

Entries are ordered by preference, most preferred first. An importer MUST ignore a value it does not know rather than reject the whole array.

Device Firmware Version

The firmware_version field takes the form <major>.<minor>.<patch>, each part a decimal integer, optionally followed by -<prerelease>.

<prerelease> may be one of the following values.

  • alpha
  • beta
  • rc
  • prerelease

Key Fields

Fields of the key object.

| field                 | optional | type   | description                                                  |
|-----------------------|----------|--------|--------------------------------------------------------------|
| key                   |          | string | BIP-0032 public key fingerprint.                             |
|-----------------------|----------|--------|--------------------------------------------------------------|
| alias                 | optional | string | User-defined alias for the key.                              |
|-----------------------|----------|--------|--------------------------------------------------------------|
| role                  | optional | enum   | Role of the key in wallet operations. See Key Roles.         |
|-----------------------|----------|--------|--------------------------------------------------------------|
| key_type              | optional | enum   | Ownership of the key. See Key Types.                         |
|-----------------------|----------|--------|--------------------------------------------------------------|
| proof_of_registration | optional | array  | Pairs of [descriptor, proof] for this key. Both are strings; |
|                       |          |        | the proof is lowercase hexadecimal.                          |

Key Roles

The role field may contain one of the following values.

  • main: Key used for normal spending conditions.
  • recovery: Key designated for recovery scenarios.
  • inheritance: Key to inherit funds if the primary user disappears.
  • cosigning: Key designated for policy-enforcing cosigning.

Key Types

The key_type field may contain one of the following values.

  • internal: User-owned key.
  • external: Key held by heirs or trusted individuals.
  • third_party: Key held by a service provider.

Transaction Fields

Fields of the transaction object. The transaction id is the key of the wallet's transactions map, not a field.

| field         | optional | type      | description                                               |
|---------------|----------|-----------|-----------------------------------------------------------|
| wtxid         | optional | string    | Witness transaction id (hex). Segwit only.                |
|---------------|----------|-----------|-----------------------------------------------------------|
| hex           | optional | string    | Raw transaction (hex).                                    |
|---------------|----------|-----------|-----------------------------------------------------------|
| fee           | optional | integer   | Transaction fee in sats.                                  |
|---------------|----------|-----------|-----------------------------------------------------------|
| block_time    | optional | timestamp | Time of the block confirming the transaction. Absent      |
|               |          |           | while unconfirmed. This and time_received are separate    |
|               |          |           | measurements and neither substitutes for the other, an    |
|               |          |           | exporter emits whichever it holds.                        |
|---------------|----------|-----------|-----------------------------------------------------------|
| time_received | optional | timestamp | When the exporting wallet first observed the transaction. |
|               |          |           | MAY be earlier than block_time.                           |
|---------------|----------|-----------|-----------------------------------------------------------|
| blockhash     | optional | string    | Confirming block hash (hex).                              |
|---------------|----------|-----------|-----------------------------------------------------------|
| blockheight   | optional | integer   | Confirming block height.                                  |
|---------------|----------|-----------|-----------------------------------------------------------|
| blockindex    | optional | integer   | Position of the transaction in the confirming block.      |
|---------------|----------|-----------|-----------------------------------------------------------|
| abandoned     | optional | boolean   | Whether the user decided to abandon this transaction.     |

Coin Fields

Fields of the coin object. Silent payment outputs are coins and use this object too, with tweak set.

| field            | optional | type    | description                                              |
|------------------|----------|---------|----------------------------------------------------------|
| outpoint         |          | string  | The outpoint, in the form `<txid>:<vout>`.               |
|------------------|----------|---------|----------------------------------------------------------|
| amount           | optional | integer | Output amount in sats.                                   |
|------------------|----------|---------|----------------------------------------------------------|
| script           | optional | string  | Output script (hex).                                     |
|------------------|----------|---------|----------------------------------------------------------|
| block_height     | optional | integer | Height of the block containing the funding transaction.  |
|                  |          |         | If null, that transaction was unconfirmed at export.     |
|------------------|----------|---------|----------------------------------------------------------|
| is_change        | optional | boolean | Whether the output was paid to a change address.         |
|------------------|----------|---------|----------------------------------------------------------|
| derivation_index | optional | integer | Index the output's address was derived at.               |
|------------------|----------|---------|----------------------------------------------------------|
| is_immature      | optional | boolean | The output is an immature coinbase output.               |
|------------------|----------|---------|----------------------------------------------------------|
| is_from_self     | optional | boolean | The funding transaction was made by this wallet.         |
|------------------|----------|---------|----------------------------------------------------------|
| frozen           | optional | boolean | The user marked this output as do-not-spend.             |
|------------------|----------|---------|----------------------------------------------------------|
| spend_status     | optional | enum    | Spend status of the output. See Spend Status.            |
|------------------|----------|---------|----------------------------------------------------------|
| tweak            | optional | string  | Silent payment outputs only: the 32-byte tweak needed    |
|                  |          |         | to derive the output, as defined by BIP-0352, encoded    |
|                  |          |         | as 64 lowercase hexadecimal characters in big-endian    |
|                  |          |         | order. Absent for ordinary outputs.                      |
|------------------|----------|---------|----------------------------------------------------------|
| sp_label         | optional | string  | Silent payment outputs only: the BIP-0352 label scalar   |
|                  |          |         | of the labelled address the output was paid to, encoded  |
|                  |          |         | as 64 lowercase hexadecimal characters in big-endian    |
|                  |          |         | order. Absent for the unlabelled address. This is         |
|                  |          |         | protocol data, not an annotation.                        |

Spend Status

The spend_status field may contain one of the following values.

  • unconfirmed: The transaction is broadcast but not yet confirmed in a block.
  • replaced: The transaction has been replaced by a transaction confirmed in a block.
  • unspent: The transaction has been confirmed in a block and the output is unspent.
  • spent: The transaction has been confirmed in a block and the output is spent.