Skip to content

BIP321: use a valid base58 example address, warn against paying it - #2230

Closed
fametrano wants to merge 1 commit into
bitcoin:masterfrom
fametrano:valid-example-address
Closed

BIP321: use a valid base58 example address, warn against paying it#2230
fametrano wants to merge 1 commit into
bitcoin:masterfrom
fametrano:valid-example-address

Conversation

@fametrano

@fametrano fametrano commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

This revives #119, which @laanwj closed in 2015 for lack of author consensus. One of three mutually exclusive options for the same problem — see the table at the bottom. My preference is #2229, not this PR; this one is here so the option is stated explicitly rather than assumed dead.

The inconsistency

BIP 321's base58 example address has a deliberately broken checksum, but the bech32/bech32m examples added after the fork from BIP 21 do not follow that convention:

Address Status on master
175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W invalid checksum (intentional)
bc1qufgy354j3kmvuch987xe4s40836x3h0lg8f5n2 valid bech32, witness v0, mainnet
bc1p5swkugezn97763tl0yty6556856uug0q6jflljvep9m4p7339x5qzyrh4g valid bech32m, witness v1, mainnet
tb1qghfhmd4zh7ncpmxl3qzhmq566jk8ckq4gafnmg valid bech32, witness v0, testnet

Three of the four are already valid, so the document is inconsistent either way. #2228 and #2229 resolve it downward (document, or extend, the invalidity). This PR resolves it upward.

This PR

Two changes:

  1. Replaces the base58 address with 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJED9L, the replacement proposed in Replace invalid example address with bip20 address #119, at all 16 occurrences. Every address in the document then has a valid checksum, so all the example URIs parse and can be used as test vectors as they stand.
  2. Adds a note that says not to pay them:

Note: The addresses used in these examples are for illustration only and must not be used to send funds.

The note is the part that answers @laanwj's objection in #119 — that a valid example address is a spendable one — by warning the reader instead of breaking the encoding. Unlike BIP 21's note, it makes no claim about validity, so it stays true regardless of which addresses the document carries.

Why that specific address: it is BIP 20's example address, and BIP 20 already pairs it with the same label=Luke-Jr these examples use, so the labels stay coherent — the objection @luke-jr raised in #119 ("maybe change the label to something else too, if it isn't going to be my address"). Verified as a valid P2PKH mainnet address.

The case for it, from the #119 thread

  • @schildbach: "from time to time, a user approaches me with a bug: Bitcoin Wallet does not parse certain bitcoin URIs. It turned out they were trying to use the malformed URIs from this document." A decade later, BIP 321 still ships those URIs.
  • @evoskuil, who opened Replace invalid example address with bip20 address #119: the examples cannot be used as test vectors as they stand, and a non-address in a field the spec defines as an address is unrepresentative — "it might as well be anything, making the example fairly pointless".

The case against, which closed #119

A note is a weaker guarantee than an unspendable string: it protects the reader who reads it, not the one who copies a URI out of a code block. The RFC analogy @laanwj drew (documentation IP ranges) argues for keeping example addresses structurally unusable, and this PR would take the document from two spendable mainnet addresses to four. That is why I still prefer #2229.

@laanwj also suggested a middle path in that thread: use testnet addresses throughout, so the examples are valid and parseable but accidental payments are harmless. That would be a fourth option, and a larger change than any of these three; happy to prepare it if that is the direction maintainers prefer.

There is also a smaller variant of this PR's approach — repairing the existing address's checksum in place, one character — which I worked out in a comment below. It has the smallest diff of anything discussed here and the largest hazard, because it resurrects a real third-party address.

The three options

PR Approach Diff
#2228 keep the addresses, word the note to match reality +2
#2229 invalidate every address, add BIP 21's note verbatim +7 / -5 my preference
#2230 make every address valid, warn against paying them +18 / -16 this PR

Only one should be merged; I'll close the other two.

My preference is #2229. It is the only one of the three that leaves no spendable address anywhere in the document, it makes BIP 21's existing wording literally true here so the two documents stay in sync, and the whole cost is four characters. #2228 is the minimal-diff fallback if maintainers would rather not touch strings that downstream implementations may already be using as test vectors. This PR is the one I would close first.

@fametrano

Copy link
Copy Markdown
Contributor Author

For completeness: there is a smaller variant of this same approach that #119 did not consider. Instead of swapping in a different address, just repair the checksum of the one already there. It is a one-character change:

before: 175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W
after:  175tWpb8K1S7NmH4Zx6rewF9WQrcZv2456
                                        ^

How I derived it: base58check-decode the existing string to its 25 bytes, keep version byte + hash160, recompute the checksum, re-encode.

version byte 0x00 (P2PKH, mainnet)
hash160 42bd6b9eeb1da01504fefe014e16415246c0f66f
checksum in document 8a9c6129
correct checksum 8a9c6111

Only the final character changes, and it is the unique fix: brute-forcing all 58 base58 characters in the last position yields exactly one valid address, ...2456. That also confirms @TheBlueMatt's recollection in #119 that the address was mangled by replacing its last character with a W.

Why I did not do it this way. Repairing the checksum restores the original address, which per that same comment was the one on the Wikipedia Bitcoin page at the time — i.e. a real address belonging to someone else, plausibly still monitored. On the accidental-payment axis that is strictly worse than #119's choice: funds sent to a mangled address bounce off the wallet's own validation, funds sent to a resurrected third-party address are simply gone. It also leaves label=Luke-Jr attached to an address that is not @luke-jr's, which is the objection raised in #119.

So the one-character fix is the smaller diff but the larger hazard, and #119's 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJED9L is the better choice within this approach: it comes from BIP 20, where it is already paired with the same label.

My overall preference remains #2229 — no spendable address anywhere in the document. But if maintainers prefer this route and want the minimal diff, say so and I will reduce this PR to the single character.

@jonatack jonatack left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree with you; I prefer #2229.

Revives bitcoin#119, closed in 2015 for lack of author consensus.

175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W has a deliberately broken checksum
-- the address from the Wikipedia Bitcoin page of the time with its
final character replaced -- while every other address in the document,
the bech32 and bech32m examples added after the fork from BIP 21, has a
valid checksum. That inconsistency has a documented cost: users have
filed URI-parsing bugs against wallets after copying URIs straight out
of the document (schildbach in bitcoin#119), and the examples cannot be used
as test vectors as they stand (evoskuil in bitcoin#119, who opened it for
exactly this reason).

Use 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJED9L, the replacement bitcoin#119 proposed.
It is BIP 20's example address, where it is already paired with the
same label=Luke-Jr used here, so the labels in the examples stay
coherent -- luke-jr's objection in bitcoin#119.

Every address in the document is now valid and parseable, so the
examples work as test vectors, and a note states that they are
illustrative and must not be paid. That addresses laanwj's objection in
bitcoin#119 -- that valid example addresses are spendable ones -- by warning
the reader rather than by breaking the encoding.

Alternatives: bitcoin#2228 and bitcoin#2229, which keep the addresses unspendable
instead.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@fametrano
fametrano force-pushed the valid-example-address branch from 459565f to 932d3f0 Compare July 31, 2026 21:19
@fametrano fametrano changed the title BIP321: replace the invalid base58 example address with a valid one BIP321: use a valid base58 example address, warn against paying it Jul 31, 2026
@fametrano

Copy link
Copy Markdown
Contributor Author

Force-pushed: the PR now also adds a note, which it previously argued was unnecessary.

Note: The addresses used in these examples are for illustration only and must not be used to send funds.

Rationale for the change of mind: making every address valid fixes the parsing complaints in #119, but on its own it leaves @laanwj's objection from that thread unanswered — a valid address is a spendable one. Warning the reader answers it without breaking the encoding, so the examples stay usable as test vectors. Note that this wording makes no claim about checksum validity, unlike BIP 21's note, so it remains true whichever addresses the document ends up carrying.

The title and description are updated accordingly. My preference is still #2229.

@jonatack

Copy link
Copy Markdown
Member

I'd suggest closing this one in favor of #2229.

@jonatack jonatack added the Fixups Minor fixups not worth bothering the BIP author(s) for label Jul 31, 2026
@jonatack jonatack closed this Jul 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Fixups Minor fixups not worth bothering the BIP author(s) for

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants