You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Currently, in Specter, there is only address labelling. The data structures are:
For the CSV:
Address,Label
bc1qj3...,some_label
For the JSON: {"labels": {"some_label": ["bc1qj3..."], ...}
Unlike for example in Electrum, where you have this structure: {"8a5e4...": "some tx id label", "bc1qj3...": "some address label"}
The tx labels are by default currently some address that is chosen to be the somewhat relevant destinaton address for the tx:
E.g. sending to bcrt1qhrk4jmxky43nf2jup7pz6336nr4py97td5szrp results in:
If you change the "tx label" it will change the label for the associated address, and vice versa, which is, in particular, problematic if you have a tx where you receive, since this can lead to unexpected results:
If you label the tx with id 63882... like this:
Now, we change the label for bcrt1q9mkrhmxcn7rslzfv6lke8859m7ntwudfjqmcx7 to:
which also changes the label for the tx itself:
Solution: Have a separate key-value pair for tx-ids and labels.
Intermediate solution: Deactivate the labels column in the tx overview.
Also, if you send to multiple recipients no label is used at all, just some html with the number of recipients is injected:
So, you couldn't label this with e.g. "Donations to different FOSS projects" or "Payments to suppliers".
What works fine here, though, is persisting labels for individual addresses. Here I simulated "loosing" somehow the label for Output 2 where I mocked the multisig address as donation address of Specter (this is regtest, don't use this!).
Type: Enhancement / Architecture Priority: MEDIUM Verdict: FIX
This is a well-documented structural issue: transaction labels are stored as address labels, causing confusing coupling where editing a tx label changes the address label (and vice versa). Multi-recipient transactions cannot be labeled at all.
The good news: BIP-329 (Wallet Labels Export Format) has been finalized since this was filed. It defines a standard JSON Lines format with separate type fields for tx, addr, pubkey, input, output, and xpub — exactly what's needed here.
Recommended approach:
Add a separate tx_labels dict ({txid: label}) alongside the existing address labels
Update the UI to distinguish address vs transaction labels
Implement BIP-329 export/import for interoperability with Sparrow and other wallets that already support it
This is a meaningful improvement for users who actively label transactions for accounting or privacy tracking.
I have been exploring a backwards-compatible BIP-329 interoperability layer for the current Specter label model. A working fork PR is available here for review and discussion:
This does not claim to solve the underlying architecture problem described in this issue. It makes the trade-off explicit:
Full long-term solution: redesign Specter's canonical label model so address, transaction, and output labels are stored independently, then map those concepts directly to BIP-329.
Backwards-compatible adapter: keep the existing address-label store and wallet backup format unchanged, but project the semantics Specter currently exposes into a separate BIP-329 JSONL import/export path.
The fork PR implements option 2.
One important detail is that the conversion is intentionally asymmetric. Specter stores an explicit address label but currently uses it as the effective label shown for that address's UTXOs. Sparrow imports BIP-329 addr and output records independently; an imported address label is not automatically propagated to existing outputs. An addr-only export would therefore preserve the address metadata but not the UTXO-label semantics users rely on for coin control.
The adapter consequently exports:
an addr record for each explicitly stored Specter address label;
an output record with the same derived label for each current known UTXO on that address;
spendable:false for frozen outputs.
These derived output records do not imply that Specter has an independent per-output label store.
The reverse mapping is deliberately not performed. Imported addr labels map directly to Specter's existing store, while arbitrary imported output.label values are reported as unsupported. Collapsing potentially different output labels—including historical outputs on a reused address—into one address label would be lossy and could change the apparent labels of unrelated transactions. Output spendable state can still map safely to Specter's existing frozen-UTXO mechanism, with pending-PSBT/Core-lock protections.
The existing Specter labels backup structure remains unchanged and no migration is introduced. The broader issue here should remain open even if the adapter approach is eventually accepted, because independent transaction/output labeling would still require the full model redesign described above.
Thanks for digging into this and for spelling out the adapter-vs-model-redesign trade-off.
I agree with keeping this issue open for the broader architectural problem: Specter still does not have independent canonical transaction/output labels, so a BIP-329 adapter should not be treated as closing the misleading-transaction-label behavior by itself.
For maintainers to review this concretely, please open the work as a draft PR against cryptoadvance/specter-desktop rather than only as a fork PR. In the PR description, the most useful review checkpoints will be:
exactly which BIP-329 record types are supported on import/export (addr, output, tx, etc.);
confirmation that imported output.label values are reported but not collapsed into Specter address labels;
how spendable:false maps to frozen UTXO state, especially around pending PSBTs and pre-existing Core locks;
whether the existing Specter JSON/CSV backup/import paths remain byte/behavior compatible;
the regression tests covering repeated-address outputs and conflicting duplicate BIP-329 records.
That will make it much easier to review the compatibility layer on its own merits while still tracking the full independent-label-model redesign here.
Follow-up: the backwards-compatible adapter is now open against upstream as #2712. The PR has a manual Testnet3 Sparrow ↔ Specter report with three screenshots, including a real frozen 38,759-sat UTXO. This implements the interoperability option discussed above; it does not add independent transaction/output label storage or resolve the misleading transaction-label behavior in this issue. Please keep #2018 open for that longer-term model redesign.
Activity
moneymanolis commentedon Dec 15, 2022
Perhaps the easiest thing is to (at least partially) implement Craig's BIP proposal, to have sth. like:
The BIP-PR is still open, not sure what is blocking the merge.
moneymanolis commentedon Dec 17, 2022
Multiple recipients
Also, if you send to multiple recipients no label is used at all, just some html with the number of recipients is injected:
So, you couldn't label this with e.g. "Donations to different FOSS projects" or "Payments to suppliers".
What works fine here, though, is persisting labels for individual addresses. Here I simulated "loosing" somehow the label for Output 2 where I mocked the multisig address as donation address of Specter (this is regtest, don't use this!).
Label lost:
Reimported the Specter JSON backup file:
al-munazzim commentedon Apr 1, 2026
Triage Assessment
Type: Enhancement / Architecture
Priority: MEDIUM
Verdict: FIX
This is a well-documented structural issue: transaction labels are stored as address labels, causing confusing coupling where editing a tx label changes the address label (and vice versa). Multi-recipient transactions cannot be labeled at all.
The good news: BIP-329 (Wallet Labels Export Format) has been finalized since this was filed. It defines a standard JSON Lines format with separate
typefields fortx,addr,pubkey,input,output, andxpub— exactly what's needed here.Recommended approach:
tx_labelsdict ({txid: label}) alongside the existing address labelsThis is a meaningful improvement for users who actively label transactions for accounting or privacy tracking.
schnuartz-ai commentedon Sep 11, 2026
I have been exploring a backwards-compatible BIP-329 interoperability layer for the current Specter label model. A working fork PR is available here for review and discussion:
schnuartz-ai#1
This does not claim to solve the underlying architecture problem described in this issue. It makes the trade-off explicit:
The fork PR implements option 2.
One important detail is that the conversion is intentionally asymmetric. Specter stores an explicit address label but currently uses it as the effective label shown for that address's UTXOs. Sparrow imports BIP-329
addrandoutputrecords independently; an imported address label is not automatically propagated to existing outputs. An addr-only export would therefore preserve the address metadata but not the UTXO-label semantics users rely on for coin control.The adapter consequently exports:
addrrecord for each explicitly stored Specter address label;outputrecord with the same derived label for each current known UTXO on that address;spendable:falsefor frozen outputs.These derived output records do not imply that Specter has an independent per-output label store.
The reverse mapping is deliberately not performed. Imported
addrlabels map directly to Specter's existing store, while arbitrary importedoutput.labelvalues are reported as unsupported. Collapsing potentially different output labels—including historical outputs on a reused address—into one address label would be lossy and could change the apparent labels of unrelated transactions. Outputspendablestate can still map safely to Specter's existing frozen-UTXO mechanism, with pending-PSBT/Core-lock protections.The existing Specter
labelsbackup structure remains unchanged and no migration is introduced. The broader issue here should remain open even if the adapter approach is eventually accepted, because independent transaction/output labeling would still require the full model redesign described above.The Sparrow behavior referenced for this decision is in its current
WalletLabelsimporter:https://github.com/sparrowwallet/sparrow/blob/3dc99b6b54a6c7a43071aa9e8852c8b2e813b6d1/src/main/java/com/sparrowwallet/sparrow/io/WalletLabels.java#L255-L306
al-munazzim commentedon Sep 11, 2026
Thanks for digging into this and for spelling out the adapter-vs-model-redesign trade-off.
I agree with keeping this issue open for the broader architectural problem: Specter still does not have independent canonical transaction/output labels, so a BIP-329 adapter should not be treated as closing the misleading-transaction-label behavior by itself.
For maintainers to review this concretely, please open the work as a draft PR against
cryptoadvance/specter-desktoprather than only as a fork PR. In the PR description, the most useful review checkpoints will be:addr,output,tx, etc.);output.labelvalues are reported but not collapsed into Specter address labels;spendable:falsemaps to frozen UTXO state, especially around pending PSBTs and pre-existing Core locks;That will make it much easier to review the compatibility layer on its own merits while still tracking the full independent-label-model redesign here.
schnuartz-ai commentedon Sep 13, 2026
Follow-up: the backwards-compatible adapter is now open against upstream as #2712. The PR has a manual Testnet3 Sparrow ↔ Specter report with three screenshots, including a real frozen 38,759-sat UTXO. This implements the interoperability option discussed above; it does not add independent transaction/output label storage or resolve the misleading transaction-label behavior in this issue. Please keep #2018 open for that longer-term model redesign.