Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
180 changes: 180 additions & 0 deletions 352.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
NIP-352
=======

Bitcoin Silent Payment Address
-------------------------------

`draft` `optional`

## Summary

A Nostr event for publishing a static Bitcoin Silent Payment address
(`sp1...`) discoverable via social identity.

## Motivation

BIP-352 Silent Payments let a sender pay a static address without
address reuse. A parallel effort, Nostr Silent Payments (NSP), defines
a deterministic derivation of an `sp1...` address from any Nostr public
key: a sender computes the recipient's SP address from their `npub`
alone, with no relay query and no action required from the receiver.

NSP's zero-action property is useful, but it fixes two things that some
receivers will want to control:

1. **No rotation.** The address is mathematically bound to the Nostr
keypair. To change it the receiver must change their Nostr identity.
2. **No opt-out.** Anyone who knows an npub can compute the payment
address. The receiver cannot separate payment identity from social
identity, nor prevent the mapping from being computed.

This NIP defines the receiver-controlled announced address layer:
the receiver signs and publishes their `sp1...` address as a Nostr
event; senders query for it before paying. The derivation of the address
from any particular key is out of scope — the protocol cares only about
what is announced, not how it was computed.

NIP-352 and NSP are complementary. NSP is a reasonable fallback when no
kind:30352 event has been published. When a kind:30352 event exists,
senders SHOULD prefer it, because it represents the receiver's explicit
and current choice.

## Event kind

**kind: 30352**

Events in the `30000–39999` range are *addressable*: for each
combination of `(kind, pubkey, d-tag value)`, relays keep only the
latest event. This gives each `(pubkey, network)` pair its own
independently replaceable slot.

`30352 = 30000 + 352 (BIP-352)`.

## Tags

| Tag | Value | Required | Description |
|-----|-------|----------|-------------|
| `d` | `"mainnet"` \| `"signet"` \| `"testnet"` | yes | Network. Forms the per-pubkey replaceable key together with `kind`. |
| `sp` | `sp1...` address | yes | The BIP-352 static payment address. |
| `payment_pubkey` | 33-byte compressed pubkey (hex) | no | The public key from which `sp` is derived. Allows receivers to prove derivation provenance without revealing the private key. Senders do not need this tag to pay. |

Content: empty string or a free-form human-readable note (ignored by
protocol implementations).

## Example

```json
{
"kind": 30352,
"pubkey": "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
"content": "",
"tags": [
["d", "mainnet"],
["sp", "sp1qqgmccn46xdv3dfts7e7y9k3m5ln7xa4rqe4rqdvnn9vp6kfzr6lqzgq..."],
["payment_pubkey", "02a1b2c3..."]
],
"created_at": 1750000000,
"id": "...",
"sig": "..."
}
```

## Discovery

To find a payment address for a given npub:

```json
{"kinds": [30352], "authors": ["<pubkey-hex>"], "#d": ["mainnet"]}
```

Take the event with the highest `created_at`. Relays SHOULD return only
the latest, but clients MUST handle duplicates from non-conforming
relays. Read the `sp` tag value. Pay using any BIP-352-compatible wallet.

## Rotation

Publish a new kind:30352 event with the same `d` tag value. The new
event replaces the old one at compliant relays. Senders SHOULD re-fetch
before initiating a payment rather than relying on cached addresses.

## Verification (optional)

If `payment_pubkey` is present, a client MAY verify that the `sp`
address encodes the correct scan and spend keys per BIP-352. This is
purely informational — a sender does not need to perform this check to
construct a valid payment.

## Rationale

**Why kind:30352 and not kind:10352?**
Events in `10000–19999` are replaceable per `(kind, pubkey)` — the
`d`-tag value is not part of the relay's deduplication key. A signet
publication would overwrite the mainnet address. The addressable range
`30000–39999` uses `(kind, pubkey, d)` as the key, so mainnet and
signet live in independent slots.

**Why not kind:0?**
Kind:0 is a single mutable blob per pubkey. Embedding an SP address
there conflates two orthogonal concerns: social profile and payment
identity. A dedicated kind allows independent rotation (publishing a new
kind:30352 does not touch the profile), supports per-network addresses
via the `d` tag, and is simpler to query, cache, and index.

**Why is derivation out of scope?**
The sender needs only the `sp1...` string to construct a BIP-352
payment. Whether the receiver derived it from their Nostr key, a
hardware wallet, or an entirely separate keypair is invisible on-chain
and irrelevant to the sender. Mandating a derivation scheme would
constrain receiver key management without any protocol benefit.

**Why is `payment_pubkey` optional?**
Most receivers will omit it. It is useful when a receiver wants to let
clients verify that `sp` was computed from a specific key they control —
for example, to prove that a deterministically derived address is
consistent with a published scheme. It is not a protocol requirement for
payment; it is a provenance hint for clients that want it.

## Implementation notes

*This section is non-normative.*

Receivers control how they derive the keypair behind their published
`sp` address. Three common approaches:

- **From the social key** — derive the SP keypair from the Nostr nsec
directly. Simple; single key to manage. Trade-off: the link between
Nostr identity and payment identity is permanent and computable by
anyone who has the nsec.

- **Deterministic sub-key** — derive a separate payment key from the
nsec via a tagged hash (e.g. `tagged_hash("nostr-payment/v1", nsec)`).
Recoverable from the nsec alone; the payment address is not computable
from the npub. Rotating means incrementing the index and republishing.

- **Independent keypair** — generate a dedicated keypair with no
relation to the Nostr key. Maximum isolation. Requires a separate
backup; losing it means losing access to received UTXOs.

Clients that want to pay an npub that has not published a kind:30352
event may fall back to NSP derivation (computing the address from the
npub directly per the NSP spec), but SHOULD make this fallback visible
to the user: the NSP-derived address ignores any rotation the receiver
may have performed and cannot be opted out of by the receiver.

## Related NIPs

- [NIP-01](01.md): Defines addressable events (`30000–39999`)
- [NIP-19](19.md): bech32 encoding used for `sp1...` addresses and npubs
- [NIP-65](65.md): Analogous pattern — per-pubkey metadata as an
addressable event
- [NSP (PR #2355)](https://github.com/nostr-protocol/nips/pull/2355):
Nostr Silent Payments — deterministic derivation of an `sp1...`
address from any `npub`, requiring no receiver action. NIP-352 is the
receiver-controlled announcement layer intended to work alongside NSP:
a published kind:30352 event takes precedence; NSP derivation is the
fallback.

## Reference implementations

- [Nostru](https://github.com/i2dor/nostru) — Chrome extension;
publishes and discovers kind:30352 events.