Bitcoin Development Mailinglist
 help / color / mirror / Atom feed
* [bitcoindev] Standardizing public key exposure classification for existing outputs
@ 2026-09-04 19:10 'duncan0k' via Bitcoin Development Mailing List
  2026-09-07 20:53 ` 'conduition' via Bitcoin Development Mailing List
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: 'duncan0k' via Bitcoin Development Mailing List @ 2026-09-04 19:10 UTC (permalink / raw)
  To: bitcoindev

Hi all,

I would like to gauge interest in a specification that defines how to
classify an existing Bitcoin output by whether the public key needed to
spend it has already been published on-chain.

The gap: BIP 360 gives us an output type whose key stays off-chain
until a script-path spend, and BIP 361 proposes a phased sunset of
legacy signature verification. Both assume the ecosystem can answer
"which existing outputs are exposed?" -- but no BIP specifies how that
question is answered.

Why this is a practical problem: published estimates of the exposed
supply currently range from roughly 25% to over 34%. As far as I can
tell the spread is definitional, not measurement error. Recurring
disagreements:

- Is a P2TR output exposed at rest? Its 32-byte output key is a public
  key, and solving its discrete log yields a working key-path spend
  regardless of how the internal key was chosen -- a NUMS internal key
  does not help, since consensus never checks how Q was constructed.

- Is a spent-from P2PKH address that still holds a balance "exposed at
  rest" or "exposed on spend"? To an adversary these are the same
  situation, but tools label them differently.

- What should a classifier report for a P2SH/P2WSH output whose script
  has never been revealed?

- What about keys disclosed off-chain -- xpubs handed to service
  providers, or spends of the corresponding output on a 2017 fork?

If BIP 361 or something like it advances, "is this output
legacy-vulnerable" becomes a question asked at scale by wallets,
explorers and custodians, with money attached. Users consulting two
tools should not get two answers about the same coins.

What the draft does: it specifies four levels -- EXPOSED_AT_REST,
EXPOSED_ON_SPEND, NOT_EXPOSED, UNDETERMINED -- a per-output-type
assignment table, and a fail-closed rule: where data is insufficient
to distinguish two levels, the more-exposed level must be assigned.
Two points I would particularly like feedback on:

1. Disclosure mechanism does not change the level. A reused,
   spent-from script that retains a balance is EXPOSED_AT_REST, the
   same as P2PK. I think separating these invites the reading that
   reused addresses are safer than P2PK, which is false. Some existing
   tools (including an earlier iteration of my own) do separate them.

2. UNDETERMINED is mandatory for unrecognized output types, rather
   than defaulting them to unexposed. Any classifier predating a
   future output type will encounter outputs it cannot reason about,
   and reporting those as safe asserts a property it has not
   established.

The draft also specifies a constant-time floor: if a script's
confirmed spent-output count is greater than zero, a spend has
occurred, and for every type except P2MR that publishes the material
the script commits to. This is what prevents a truncated history scan
from producing a false NOT_EXPOSED -- without it, every implementation
independently decides what to report when it runs out of scan budget,
and the divergence reappears at the engineering layer. (The one
over-approximation -- a revealed script that requires no signature --
errs in the conservative direction, which the fail-closed rule
permits; see the v0.2.0 changelog.)

Explicitly out of scope: risk scoring. Turning exposure into a number
requires weighing balance, dormancy and CRQC timelines, none of which
are observable on-chain and all of which are contested. The draft
stops at the observable so that the numbers people compute on top of
it are at least computed over the same facts.

Draft, reference implementation and test vectors:
https://github.com/duncan0k/pubkey-exposure-classification

I posted this to Delving Bitcoin a couple of days ago and am
cross-posting here for wider review:
https://delvingbitcoin.org/t/standardizing-an-exposure-classification-for-existing-outputs-pre-bip/2866

Before I invest further: is this something the list considers worth
specifying, or is it better left to each implementation? I am also
interested in whether anyone has prior art I have missed -- I could
not find a canonical definition, but this is the kind of thing that
gets rediscovered.

duncan0k

-- 
You received this message because you are subscribed to the Google Groups "Bitcoin Development Mailing List" group.
To unsubscribe from this group and stop receiving emails from it, send an email to bitcoindev+unsubscribe@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/bitcoindev/010001a06dd4cdd9-b8082042-8750-4e9a-917e-2053c919e4c4-000000%40email.amazonses.com.


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [bitcoindev] Standardizing public key exposure classification for existing outputs
  2026-09-04 19:10 [bitcoindev] Standardizing public key exposure classification for existing outputs 'duncan0k' via Bitcoin Development Mailing List
@ 2026-09-07 20:53 ` 'conduition' via Bitcoin Development Mailing List
  2026-09-08  3:53   ` 'duncan0k' via Bitcoin Development Mailing List
  2026-09-14 21:04 ` 'duncan0k' via Bitcoin Development Mailing List
  2026-09-18 10:38 ` 'duncan0k' via Bitcoin Development Mailing List
  2 siblings, 1 reply; 5+ messages in thread
From: 'conduition' via Bitcoin Development Mailing List @ 2026-09-07 20:53 UTC (permalink / raw)
  To: duncan0k; +Cc: bitcoindev


[-- Attachment #1.1: Type: text/plain, Size: 8403 bytes --]

Hi Duncan,

Disclaimer: I haven't read the draft BIP; it appears to be AI-generated. If you don't have time to write your own BIP, you should not expect others to have time to read it.

> Before I invest further: is this something the list considers worth
> specifying, or is it better left to each implementation? 


I think it is an important question to answer. A deterministic standardized way to index what "exposed pubkey" means is beneficial to everyone involved in the PQ conversation.

My work on DropKick and Tadge Dryja's work on Lifeboat are both contingent on this source of truth, but nobody has yet spent the cycles to figure out how that would work.

Methodology is still an open problem too. Would every full node go back and reindex the entire chain to collect a list of exposed pubkeys/addresses? That seems expensive, but at least an upgraded node could start preparing early, before any fork is activated.

Perhaps this is an excuse for bitcoind to finally include an address index? This would basically solve the engineering problem as a drive-by.


> I am also interested in whether anyone has prior art I have missed -- I could
> not find a canonical definition, but this is the kind of thing that
> gets rediscovered.

I would check out Project Eleven's dashboard [2] if you haven't already. 



> Is a P2TR output exposed at rest?

If you consider the internal key + MAST root to be a preimage, then no: P2TR is actually usable without exposing that preimage, unless you do a script spend. 


However, not every P2TR address is guaranteed to HAVE an internal key. Some non-standard implementations might have disregarded BIP341's recommendations, and put a bare untweaked pubkey on chain. It's impossible to know for sure. 


Personally I doubt this is a significant share of the P2TR supply - Every codebase i've ever seen that implements P2TR does so with an empty tweak, as recommended by the spec.

Still, it means when considering rescue protocols that locking P2TR coins under a new encumbrance that says "you can only spend by proving knowledge of the internal key" will confiscate some unknown (probably tiny) fraction of P2TR coins.


> Is a spent-from P2PKH address that still holds a balance "exposed at rest" or "exposed on spend"?

Exposed at rest, i.e. vulnerable to 'long exposure' attacks.

> What should a classifier report for a P2SH/P2WSH output whose script has never been revealed?

I would say "unexposed" for this. The signer definitely knows something (a script) that the CRQC doesn't.

> What about keys disclosed off-chain -- xpubs handed to service
> providers, or spends of the corresponding output on a 2017 fork?

I strongly doubt we can do much about off-chain exposure.

regards,
conduition

[1]: https://github.com/bitcoin/bips/pull/1895#pullrequestreview-4110112784
[2]: https://www.projecteleven.com/bitcoin-risq-list


On Friday, September 4th, 2026 at 12:25 PM, 'duncan0k' via Bitcoin Development Mailing List <bitcoindev@googlegroups.com> wrote:

> Hi all,
> 

> I would like to gauge interest in a specification that defines how to
> classify an existing Bitcoin output by whether the public key needed to
> spend it has already been published on-chain.
> 

> The gap: BIP 360 gives us an output type whose key stays off-chain
> until a script-path spend, and BIP 361 proposes a phased sunset of
> legacy signature verification. Both assume the ecosystem can answer
> "which existing outputs are exposed?" -- but no BIP specifies how that
> question is answered.
> 

> Why this is a practical problem: published estimates of the exposed
> supply currently range from roughly 25% to over 34%. As far as I can
> tell the spread is definitional, not measurement error. Recurring
> disagreements:
> 

> - Is a P2TR output exposed at rest? Its 32-byte output key is a public
>   key, and solving its discrete log yields a working key-path spend
>   regardless of how the internal key was chosen -- a NUMS internal key
>   does not help, since consensus never checks how Q was constructed.
> 

> - Is a spent-from P2PKH address that still holds a balance "exposed at
>   rest" or "exposed on spend"? To an adversary these are the same
>   situation, but tools label them differently.
> 

> - What should a classifier report for a P2SH/P2WSH output whose script
>   has never been revealed?
> 

> - What about keys disclosed off-chain -- xpubs handed to service
>   providers, or spends of the corresponding output on a 2017 fork?
> 

> If BIP 361 or something like it advances, "is this output
> legacy-vulnerable" becomes a question asked at scale by wallets,
> explorers and custodians, with money attached. Users consulting two
> tools should not get two answers about the same coins.
> 

> What the draft does: it specifies four levels -- EXPOSED_AT_REST,
> EXPOSED_ON_SPEND, NOT_EXPOSED, UNDETERMINED -- a per-output-type
> assignment table, and a fail-closed rule: where data is insufficient
> to distinguish two levels, the more-exposed level must be assigned.
> Two points I would particularly like feedback on:
> 

> 1. Disclosure mechanism does not change the level. A reused,
>    spent-from script that retains a balance is EXPOSED_AT_REST, the
>    same as P2PK. I think separating these invites the reading that
>    reused addresses are safer than P2PK, which is false. Some existing
>    tools (including an earlier iteration of my own) do separate them.
> 

> 2. UNDETERMINED is mandatory for unrecognized output types, rather
>    than defaulting them to unexposed. Any classifier predating a
>    future output type will encounter outputs it cannot reason about,
>    and reporting those as safe asserts a property it has not
>    established.
> 

> The draft also specifies a constant-time floor: if a script's
> confirmed spent-output count is greater than zero, a spend has
> occurred, and for every type except P2MR that publishes the material
> the script commits to. This is what prevents a truncated history scan
> from producing a false NOT_EXPOSED -- without it, every implementation
> independently decides what to report when it runs out of scan budget,
> and the divergence reappears at the engineering layer. (The one
> over-approximation -- a revealed script that requires no signature --
> errs in the conservative direction, which the fail-closed rule
> permits; see the v0.2.0 changelog.)
> 

> Explicitly out of scope: risk scoring. Turning exposure into a number
> requires weighing balance, dormancy and CRQC timelines, none of which
> are observable on-chain and all of which are contested. The draft
> stops at the observable so that the numbers people compute on top of
> it are at least computed over the same facts.
> 

> Draft, reference implementation and test vectors:
> https://github.com/duncan0k/pubkey-exposure-classification
> 

> I posted this to Delving Bitcoin a couple of days ago and am
> cross-posting here for wider review:
> https://delvingbitcoin.org/t/standardizing-an-exposure-classification-for-existing-outputs-pre-bip/2866
> 

> Before I invest further: is this something the list considers worth
> specifying, or is it better left to each implementation? I am also
> interested in whether anyone has prior art I have missed -- I could
> not find a canonical definition, but this is the kind of thing that
> gets rediscovered.
> 

> duncan0k
> 

> --
> You received this message because you are subscribed to the Google Groups "Bitcoin Development Mailing List" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to bitcoindev+unsubscribe@googlegroups.com.
> To view this discussion visit https://groups.google.com/d/msgid/bitcoindev/010001a06dd4cdd9-b8082042-8750-4e9a-917e-2053c919e4c4-000000%40email.amazonses.com.
> 

-- 
You received this message because you are subscribed to the Google Groups "Bitcoin Development Mailing List" group.
To unsubscribe from this group and stop receiving emails from it, send an email to bitcoindev+unsubscribe@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/bitcoindev/9QUT0_vQUMszAr1ZQw9EsjX9S-gnVFJDD7g4eYgeovhYaOu84nmqJUs8vuDtaPSexGIKkiG3xNpo_jEnVMeJPSnxARXvcOah5jujNBBOdeU%3D%40proton.me.

[-- Attachment #1.2: publickey - conduition@proton.me - 0x474891AD.asc --]
[-- Type: application/pgp-keys, Size: 649 bytes --]

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 343 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [bitcoindev] Standardizing public key exposure classification for existing outputs
  2026-09-07 20:53 ` 'conduition' via Bitcoin Development Mailing List
@ 2026-09-08  3:53   ` 'duncan0k' via Bitcoin Development Mailing List
  0 siblings, 0 replies; 5+ messages in thread
From: 'duncan0k' via Bitcoin Development Mailing List @ 2026-09-08  3:53 UTC (permalink / raw)
  To: bitcoindev; +Cc: conduition

Hi conduition,

Thanks for engaging with the substance despite your reservations.
Answering the disclaimer straight first:

> Disclaimer: I haven't read the draft BIP; it appears to be
> AI-generated.

Partially fair, so I'll be precise about it: I used an LLM to help
draft the English text, and I won't pretend otherwise. What I'd push
back on is the implication that the content is machine-generated.
The classification was extracted from a scanner running in
production against mainnet; the fail-closed rules each correspond to
a failure mode we actually hit (truncated indexer history, the P2PK
blind spot of address-indexed APIs); the v0.2.0 revisions came from
review finding real holes. The test vectors are independently
verifiable either way. If the prose style gets in the way of review,
I'll rewrite it plainer -- the semantics are what I'm asking people
to check.

> My work on DropKick and Tadge Dryja's work on Lifeboat are both
> contingent on this source of truth

This is the kind of consumer I hoped existed. I'd like to understand
what shape DropKick needs: per-output levels at a given height? A
committed set? That determines whether script-level classification
is sufficient or an outpoint-level profile is needed.

> Would every full node go back and reindex the entire chain to
> collect a list of exposed pubkeys/addresses?

The draft deliberately stops at semantics -- what conclusion is
sound given what data -- so it doesn't presuppose any index. The
constant-time floor exists for implementations that only have
aggregate spent-counts. A node-level exposure index (or the
address-index drive-by) would be the natural next layer, and worth
its own thread; the semantics shouldn't depend on it.

> I would check out Project Eleven's dashboard

I have -- the RISQ list is the closest prior art I know of. The gap
it leaves is that a dashboard applies a methodology; it doesn't
specify one that implementations can be checked against. Different
tools citing 25%-34% is the symptom.

> If you consider the internal key + MAST root to be a preimage,
> then no: P2TR is actually usable without exposing that preimage

I think we're answering two different questions, and the draft
should name both. Mine: can a CRQC spend it under current consensus
rules? For P2TR yes -- solving the dlog of Q yields a key-path
spend; the attacker never needs P or the MAST root. Yours: does the
holder retain a secret a CRQC lacks, usable under a future rescue
encumbrance ("prove knowledge of the internal key")? For
BIP341-conformant outputs yes -- and your own point that some
outputs may be bare untweaked keys, indistinguishable on-chain, is
exactly why any such rescue confiscates an unknown fraction, and why
the draft classifies by attacker-spendability (observable) rather
than rescue-provability (not). I'll add a note distinguishing the
two, crediting this exchange.

> I would say "unexposed" for this. The signer definitely knows
> something (a script) that the CRQC doesn't.

I believe we agree on substance and my naming misled you -- useful
signal in itself. That case is EXPOSED_ON_SPEND in the draft,
defined as "not disclosed; spending will necessarily publish key
material" -- safe at rest, your reasoning exactly. NOT_EXPOSED is
reserved for outputs whose spend reveals nothing reusable (P2MR
script paths). If EXPOSED_ON_SPEND reads as "already exposed", the
label is doing harm; EXPOSED_WHEN_SPENT may be better. Open to
suggestions.

> I strongly doubt we can do much about off-chain exposure.

Agreed -- the draft scopes it out for that reason. The levels state
what the chain shows, nothing more.

I'll fold the P2TR note and the naming question into v0.3.0.

duncan0k

-- 
You received this message because you are subscribed to the Google Groups "Bitcoin Development Mailing List" group.
To unsubscribe from this group and stop receiving emails from it, send an email to bitcoindev+unsubscribe@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/bitcoindev/010001a07f268952-f2dff00c-20e0-4c9f-8a8b-344a35df0c6b-000000%40email.amazonses.com.


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [bitcoindev] Standardizing public key exposure classification for existing outputs
  2026-09-04 19:10 [bitcoindev] Standardizing public key exposure classification for existing outputs 'duncan0k' via Bitcoin Development Mailing List
  2026-09-07 20:53 ` 'conduition' via Bitcoin Development Mailing List
@ 2026-09-14 21:04 ` 'duncan0k' via Bitcoin Development Mailing List
  2026-09-18 10:38 ` 'duncan0k' via Bitcoin Development Mailing List
  2 siblings, 0 replies; 5+ messages in thread
From: 'duncan0k' via Bitcoin Development Mailing List @ 2026-09-14 21:04 UTC (permalink / raw)
  To: bitcoindev

A short update: the draft is at v0.4.0.

Changes since the original post, with credit:

- v0.2.0: the derived condition now requires a complete spend recipe;
  the partial-history UNDETERMINED rule is scoped to history-dependent
  classifications; the aggregate-counter floor notes its conservative
  over-approximation for revealed scripts that need no signature.

- v0.3.0, after conduition's review here: attacker-spendability is
  distinguished from holder-provability, with the P2TR discussion
  naming both questions. The EXPOSED_ON_SPEND naming problem is
  recorded as open, EXPOSED_WHEN_SPENT the leading alternative.

- v0.4.0, after wallet feedback on Delving: the Abstract and
  Motivation are rewritten to state the reasoning directly, opening
  with the misclassification in my own tooling that started this.
  Appendix A (informative) gives each level a fixed action key and a
  one-line floor; wallets own the wording above it.

Draft, reference implementation and vectors:
https://github.com/duncan0k/pubkey-exposure-classification

I would still like to hear from anyone who considers this out of
scope for a BIP. Absent that, I intend to open a pull request against
bitcoin/bips in the coming weeks.

duncan0k

-- 
You received this message because you are subscribed to the Google Groups "Bitcoin Development Mailing List" group.
To unsubscribe from this group and stop receiving emails from it, send an email to bitcoindev+unsubscribe@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/bitcoindev/010001a0a1bc23e2-e1ac88ef-2f25-4561-ad02-11e943a2cda8-000000%40email.amazonses.com.


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [bitcoindev] Standardizing public key exposure classification for existing outputs
  2026-09-04 19:10 [bitcoindev] Standardizing public key exposure classification for existing outputs 'duncan0k' via Bitcoin Development Mailing List
  2026-09-07 20:53 ` 'conduition' via Bitcoin Development Mailing List
  2026-09-14 21:04 ` 'duncan0k' via Bitcoin Development Mailing List
@ 2026-09-18 10:38 ` 'duncan0k' via Bitcoin Development Mailing List
  2 siblings, 0 replies; 5+ messages in thread
From: 'duncan0k' via Bitcoin Development Mailing List @ 2026-09-18 10:38 UTC (permalink / raw)
  To: bitcoindev

The draft is now at v0.5.1 and submitted to the BIPs repository as an
Informational BIP:

  https://github.com/bitcoin/bips/pull/2294

Two things changed since the v0.4.0 note, both after murch's review on
Delving:

- The first two levels are now stated as BIP 360's long exposure and
  short exposure vulnerabilities, per output, and the draft cites that
  section as the source of the taxonomy.

- P2MR was wrong. My original post said a spend publishes key material
  for every type except P2MR. That is false: a leaf spend puts the leaf
  script, its Merkle path and a secp256k1 key in the mempool, the same
  race as P2WSH. P2MR is EXPOSED_ON_SPEND until post-quantum leaves
  exist, and NOT_EXPOSED has no member today.

Draft, reference implementation and 25 vectors:

  https://github.com/duncan0k/pubkey-exposure-classification

Publication of an Informational BIP depends on feedback on the PR, so if
you have a view either way, that is where it counts.

duncan0k

-- 
You received this message because you are subscribed to the Google Groups "Bitcoin Development Mailing List" group.
To unsubscribe from this group and stop receiving emails from it, send an email to bitcoindev+unsubscribe@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/bitcoindev/010001a0b418f0f2-92c7e013-aea0-4707-ab25-06beafce173a-000000%40email.amazonses.com.


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-09-18 11:30 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-04 19:10 [bitcoindev] Standardizing public key exposure classification for existing outputs 'duncan0k' via Bitcoin Development Mailing List
2026-09-07 20:53 ` 'conduition' via Bitcoin Development Mailing List
2026-09-08  3:53   ` 'duncan0k' via Bitcoin Development Mailing List
2026-09-14 21:04 ` 'duncan0k' via Bitcoin Development Mailing List
2026-09-18 10:38 ` 'duncan0k' via Bitcoin Development Mailing List

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox