← index

Descriptor syntax for hash preimages

An archive of delvingbitcoin.org · view original topic →

· jaonoctus · #1 ·

Summary

Descriptors can carry private keys (pk(WIF/xprv)) and return them with listdescriptors private=true, but there is no equivalent for the secrets of miniscript hash fragments. I’d like to discuss adding a private form, e.g. sha256(preimage(HEX)), and the same for hash256, ripemd160 and hash160, possibly as a new BIP extending BIP 379.

Motivation

I ran into this while solving the TABConf / Michael Tidwell CTB challenge, where spending required providing a hash preimage. I expected it to work like pk(WIF/xprv): put the secret in the descriptor, import it, and let the wallet build and sign the transaction.

Instead, there is currently no way to give a preimage to Bitcoin Core’s wallet:

Why preimages are closer to keys than to signatures

#24114 suggests descriptors could eventually replace most of SignatureData, “everything except signatures/preimages”. Signatures commit to a specific transaction, so they can never be part of a descriptor. A preimage does not: once generated (or given to you ahead of time), it is a long-lived secret that depends only on the script. That is exactly what a private key is.

Keys Hashes
Public pk(PUBKEY) sha256(DIGEST)
Private pk(WIF/xprv) (none right now)

In @sipa’s words from the same issue:

if we keep adding exceptions, perhaps the philosophy is wrong.

“Descriptors may carry private keys but not preimages” looks like one of those exceptions.

Sketch/Draft:

This does not replace the PSBT path: preimages learned at spend time (e.g. from a counterparty in an HTLC) still belong in PSBT fields. It only covers preimages known when the descriptor is created.

Open questions

  1. Marker syntax: preimage(HEX) nested inside the fragment, a prefix, or something else?
  2. Scope: an amendment to BIP 379, or a separate BIP like other descriptor extensions?
  3. Complementary RPC: independently of descriptors, should Core get an RPC to add hash preimages to a PSBT, for the learned-at-spend-time case?
  4. Signers/hardware wallets: would devices that accept miniscript descriptors want to handle preimage secrets, or should this be software-wallet only?
  5. Deterministic preimages: is there interest in deriving preimages from key material (similar to how Lightning derives secrets), or is a literal preimage enough for a first step?

Related threads: Feature discussion: partial descriptors/miniscript · Issue #24114 · bitcoin/bitcoin · GitHub , Tr(): rawnode() and rawleaf() support, Unspendable keys in descriptors, BIP352 private key formats.

· Ferdinando Ametrano · #2 ·

A literal preimage stops being secret once one output is spent through its hash branch, and in a ranged descriptor every other output shares that branch.

Hash fragments take a digest, not a key expression, so sha256(preimage(HEX)) gives the same digest at every index of a /* descriptor. After one spend through the hash path, the preimage is on chain. The s property still keeps the other outputs safe, since each needs a signature, but their hash condition no longer adds anything. A private key is different: spending does not reveal it. So “a secret like a WIF” holds only until the first spend. Your question on deterministic preimages may be the answer: a preimage derived per index from key material gives each output its own digest. A first step with literal preimages could state the limit.

The private and public strings will have different checksums, as with keys. The BIP should say so, since this is new for a hash fragment.

btclib-wallet, a library I maintain, has no preimage(HEX) syntax yet, but its parser already gives the expected script for the digest form of all four fragments. I can add the private form and compute test vectors: each private descriptor must give the same script as the one written with the digest, and its public string must print that digest.