0329 - Draft - Informational - Aug. 23, 2022 (3 years, 10 months ago)
23
2022
BIP: 329
Layer: Applications
Title: Wallet Labels Export Format
Author: Craig Raw <[email protected]>
Comments-Summary: No comments yet.
Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP 329
Status: Draft
Type: Informational
Created: 2022-08-23
License: BSD-2-Clause
This document specifies a format for the export of labels that may be attached to various common types of records in a wallet.
This BIP is licensed under the BSD 2-clause license.
The export and import of funds across different Bitcoin wallet applications is well defined through standards such as BIP 39, BIP 32, BIP 44 etc. These standards are well supported and allow users to move easily between different wallets. There is, however, no defined standard to transfer any labels the user may have applied to the transactions, addresses, public keys, inputs, outputs or xpubs in their wallet. The UTXO model that Bitcoin uses makes these labels particularly valuable as they may indicate the source of funds, whether received externally or as a result of change from a prior transaction. In both cases, care must be taken when spending to avoid undesirable leaks of private information.
Labels provide valuable guidance in this regard, and have even become mandatory when spending in several Bitcoin wallets. Allowing users to import and export their labels in a standardized way ensures that they do not experience lock-in to a particular wallet application. In addition, many wallets allow unspent outputs to be frozen or made unspendable within the wallet. Since this wallet-related metadata is similar to labels and not captured elsewhere, it is also included in this format.
While there is currently no widely accepted format for exporting and importing labels, there are existing formats in use. SLIP-0015 1 defines a format for exporting address and output labels, but requires encryption using a private key associated with the wallet seed, and thus cannot be used independently by coordinator wallets which cannot access private keys. The Electrum wallet imports and exports address and transaction labels in a JSON format which could be used with other record types, but the format used is not self describing making record type identification difficult.
In order to be lightweight, human readable and well structured, this BIP uses a JSON format. Further, the JSON Lines format is used (also called newline-delimited JSON) 2 . This allows a document to be split, streamed, or incrementally added to, and limits the potential for formatting errors to invalidate an entire import. It is also a convenient format for command-line processing, which is often line-oriented.
Further to the JSON Lines specification, an export of labels from a
wallet must be a UTF-8 encoded text file, containing one record per line
consisting of a valid JSON object. Lines are separated by
\n
. Multiline values are not permitted. Each JSON object
must contain 3 or 4 key/value pairs, defined as follows:
| Key | Description |
|---|---|
|
|
One of
|
|
|
Reference to the transaction, address, public key, input, output or extended public key |
|
|
The label applied to the reference |
|
|
Optional key origin information referencing the wallet associated with the label |
|
|
One of
|
The reference is defined for each
type
as follows:
| Type | Description | Example |
|---|---|---|
|
|
Transaction id in hexadecimal format |
|
|
|
Address in base58 or bech32 format |
|
|
|
32, 33 or 65 byte public key in hexadecimal format |
|
|
|
Transaction id and input index separated by a colon |
|
|
|
Transaction id and output index separated by a colon |
|
|
|
Extended public key as defined by BIP 32 |
|
Each JSON object must contain both
type
and
ref
properties. The
label
,
origin
and
spendable
properties are optional. If the
label
or
spendable
properties are omitted, the
importing wallet should not alter these values. The
spendable
property should only appear where type is
output
.
If present, the optional
origin
property must contain an
abbreviated output descriptor (as defined by BIP 380
3
)
describing a BIP 32 compatible originating wallet, including all key
origin information but excluding any actual keys, any child path
elements, or a checksum. This property should be used to disambiguate
transaction labels from different wallets contained in the same export,
particularly when exporting multiple accounts derived from the same
seed.
Care should be taken when exporting due to the privacy sensitive nature of the data. Encryption in transit over untrusted networks is highly recommended, and encryption at rest should also be considered. Unencrypted exports should be deleted as soon as possible. For security reasons no private key types are defined.
The nature of this format makes it naturally extensible to handle other record types. However, importing wallets complying to this specification should ignore types not defined here.
The following fragment represents a wallet label export:
{ "type": "tx", "ref": "f91d0a8a78462bc59398f2c5d7a84fcff491c26ba54c4833478b202796c8aafd", "label": "Transaction", "origin": "wpkh([d34db33f/84'/0'/0'])" }
{ "type": "addr", "ref": "bc1q34aq5drpuwy3wgl9lhup9892qp6svr8ldzyy7c", "label": "Address" }
{ "type": "pubkey", "ref": "0283409659355b6d1cc3c32decd5d561abaac86c37a353b52895a5e6c196d6f448", "label": "Public Key" }
{ "type": "input", "ref": "f91d0a8a78462bc59398f2c5d7a84fcff491c26ba54c4833478b202796c8aafd:0", "label": "Input" }
{ "type": "output", "ref": "f91d0a8a78462bc59398f2c5d7a84fcff491c26ba54c4833478b202796c8aafd:1", "label": "Output", "spendable": false }
{ "type": "xpub", "ref": "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8", "label": "Extended Public Key" }
{ "type": "tx", "ref": "f546156d9044844e02b181026a1a407abfca62e7ea1159f87bbeaa77b4286c74", "label": "Account #1 Transaction", "origin": "wpkh([d34db33f/84'/0'/1'])" }
If the goal is solely to move labels between cooperating wallets, then the above values are the minimum needed. However, wallet data exports can serve other purposes. Many values associated with addresses, transactions and outputs are already on hand for the wallet generating the export, and yet would be hard or impossible for importing tools to reconstruct.
All of the following values are optional for the exporter to provide, but should be given if they are readily available.
height
: An integer giving the block height where this
fully confirmed transaction can be found. For transactions that are
confirmed by less than 6 blocks, omit this field or provide a value of
zero. (Background: Until it is fully confirmed, the "height" of a
transaction is in flux and may vary due to chain reorgs. However, the
consumer of the labels, may not know the current block height, so it
cannot know if the height is "real" (firm, fixed) or just transitory.
Therefore, it is important to omit the height unless the generating
wallet considers the transaction to be confirmed.)
time
: ISO-8601 formatted timestamp of the block given
by the "height" field, preferably in UTC, although ISO-8601 can
represent local times. Example:
2025-01-23T11:40:35Z
.
fee
: Integer giving the number of Satoshis that went to
the miner for this transaction.
value
: Signed integer giving the number of Satoshis
that came into the wallet by this transaction. Will be negative when
sats leave the wallet. Could be zero if it is a consolidation
transaction that moves from old UTXO to new.
rate
: Exchange rate at time of transaction. This is the
value of a Bitcoin, expressed in another currency, at the time of the
transaction, based on user preferences for data source. Multiple
currencies can be given. Keys are ISO 4217 currency codes where
possible. Example:
"rate": { "USD": 105620.00 }
keypath
: The data needed to build full descriptor down
to the specific address. This extends
origin
with the final
two components that are unhardened (in the typical case, assuming BIP
84). Provide string
/1/123
for
wpkh([d34db33f/84'/0'/0'/1/123])
. If the first character is
not
/
, then it should be interpreted as a full descriptor,
independent of
origin
(if any).
value
: Integer with the number of Satoshis
(
nValue
) of the input or output.
fmv
: Fair market value of the input/output relative to
some other currency, typically fiat. The value should be a mapping, from
currency code to decimal number. Example:
"fmv": { "USD": 1233.45 }
. Most situations will have only a
single currency value, and it represents the real price of the
goods/services expressed in some fiat currency. This is not an exchange
*rate*, but an absolute value. By dividing by the
value
(above), it is possible to calculate an effective change rate for the
transaction.
height
and
time
: Same definition as
defined in Transactions.
heights
: a list of block heights that contain any
activity related to this address, include outputs that deposit to the
address, and transactions that spend UTXOs of this address. Omit heights
for transactions that are not fully confirmed. An empty array indicates
the address is unused for confirmed transactions.
JSON can serialize a number of basic types, including string, integer
and boolean (true/false). Decimal values (
123.45
) can also
be serialized, but some parsing libraries may interpret them as floating
point values, which is generally not what we want in financial
applications. When hand-crafting JSON data, be careful not to write
"false"
(with quotes), since that is a string with 5
characters and not a boolean.