Skip to content

Deterministic pay to public key generation#331

Open
lescuer97 wants to merge 2 commits intocashubtc:mainfrom
lescuer97:p2pk_recovery
Open

Deterministic pay to public key generation#331
lescuer97 wants to merge 2 commits intocashubtc:mainfrom
lescuer97:p2pk_recovery

Conversation

@lescuer97
Copy link
Contributor

@lescuer97 lescuer97 commented Jan 19, 2026

Adds a standard way to generate keys for wallets to generate private keys for usage in P2PK operations.


- 129372': Registered SLIP-0044 coin type for Cashu.
- 10': Purpose for generating private keys for usage in P2PK.
- {counter}: Incrementing counter encoded as an unsigned 64-bit integer in big-endian format.
Copy link
Contributor

Choose a reason for hiding this comment

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

is this using BIP32? Should be more clear.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes, I'll make it clearer

13.md Outdated

Wallet are able to generate private keys to then have proofs be locked to them.

The following path is used for derivation of those keys: `m/129372'/10'/0'/0'/{counter}`:
Copy link
Contributor

Choose a reason for hiding this comment

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

`m/129372'/10'/0'/0'/{counter}`:

not using per-keyset derivation. are we sure about this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes, because it's for locking up proofs it should be more general

@robwoodgate
Copy link
Contributor

Keysets v2 is moving away from a BIP32 style derivation scheme, and using a KDF instead. Would it not be better to align with this approach, eg using a domain separator like b"Cashu_KDF_HMAC_SHA256_P2PK" or b"Cashu_P2PK_v1"?

Also, I assume the counter is separate to the one used for secrets/blinded messages. If so, this should be made clearer.

Finally, related to @a1denvalu3's comment - what happens if the derived key is out of range? Should it be discarded (as per BIP-32) or reduced modulo N?

@prusnak
Copy link
Collaborator

prusnak commented Jan 20, 2026

Keysets v2 is moving away from a BIP32 style derivation scheme, and using a KDF instead. Would it not be better to align with this approach, eg using a domain separator like b"Cashu_KDF_HMAC_SHA256_P2PK" or b"Cashu_P2PK_v1"?

Good point 👍

@lescuer97
Copy link
Contributor Author

@robwoodgate @a1denvalu3 just changed the wording around the NUT so it's a bit more clear.

robwoodgate

This comment was marked as duplicate.

Copy link
Contributor

@robwoodgate robwoodgate left a comment

Choose a reason for hiding this comment

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

Suggestion to tighten language, otherwise concept ACK

- 10': Purpose for generating private keys for usage in P2PK.
- {counter}: Incrementing counter encoded as an unsigned 64-bit integer in big-endian format.

This will allow wallets to swap proof that are still locked to a public key during a restore process.
Copy link
Contributor

@robwoodgate robwoodgate Jan 22, 2026

Choose a reason for hiding this comment

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

Suggested change
This will allow wallets to swap proof that are still locked to a public key during a restore process.
Wallets can deterministically generate private keys for P2PK using the following BIP32 derivation path:
`m/129372'/10'/0'/0'/{counter}`
Where:
- Purpose' = `129372'` (UTF-8 for 🥜)
- Coin type' = `10'` - reserved for generating private keys.
- `{counter}` is an Incrementing counter, encoded as an unsigned 64-bit integer in big-endian format.
This allows wallets to swap Proofs still locked to a corresponding public key during a restore process.
In line with BIP-32, if the resulting private key is out of range (`> N`), it should be discarded.


Wallet are able to generate private keys is a deterministic way to have proofs locked to them.

The following BIP32 derivation path for derivation of the key: `m/129372'/10'/0'/0'/{counter}`:
Copy link
Collaborator

@prusnak prusnak Jan 22, 2026

Choose a reason for hiding this comment

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

Can you explain why the last element is not hardened?

Is the xpub of m/129372'/10'/0'/0' ever shared anywhere?

If it is not shared, then instead of hardening it, I propose we change the scheme to Cashu_KDF_HMAC_SHA256 (same as used in Keyset v2, since BIP32 used in Keyset v1 is deprecated).

Copy link
Contributor Author

@lescuer97 lescuer97 Jan 26, 2026

Choose a reason for hiding this comment

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

We are following what Bitcoin does when it comes to key derivation for locking.

there is no reason right now for sharing an XPUB but can't guarantee that in the future.

The reason we want to use bip32 is because Bip32 is specifically made for this case.The Cashu_KDF_HMAC_SHA256 scheme is used because of aggregation to avoid certain issues when generating the keyset id.

This keys are never aggregated and are use individually.

Copy link
Collaborator

Choose a reason for hiding this comment

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

The reason we want to use bip32 is because Bip32 is specifically made for this case.

No, it's not. BIP32 usecase is when you need to share a pubkey for a certain key subtree. Unless you need this requirement, going with Cashu_KDF_HMAC_SHA256 is simply faster and easier.

Copy link
Contributor

Choose a reason for hiding this comment

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

@prusnak if we get the option to query the mint for quotes connected to a pubkey via NUT-20, public key derivation would become more meaningful than it currently is. I can not think of a usecase right now, but with this, extended keys would be able to essentially create a watch-only wallet of a wallets quotes, without spending from it.

So either we think about proper usecases for this for 2 weeks and go with HMAC if we can't find any, or we take the performance L, go with BIP32 and hope someone finds a usecase some day in the future

Copy link
Collaborator

Choose a reason for hiding this comment

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

if we want to have a watch-only wallet eventually which should show p2pk tokens too, this seems like a good use-case. ACK

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Backlog

Development

Successfully merging this pull request may close these issues.

5 participants