docs: update onchain-zap + headers-explorer plans for NIP-BC inline SPV tags
nostr-protocol/nips#2332 adds optional ["block", …] and ["proof", …] tags on kind:8333 that ship the SPV proof inline. The data-model side is already shipped in Quartz (BlockTag, ProofTag, OnchainZapEvent.block()/.proof() and the TagArray helpers), but no production code path produces or consumes either tag yet. amethyst/plans/2026-05-14-onchain-zaps.md — onchain zaps plan: - Update the "Chain backend" decision bullet to flag the spec change and the two production gaps (send-side emit, receive-side consume). - Add a dedicated "Inline SPV proofs" section covering: spec status and the merkle-proof encoding ambiguity flagged back to the PR; per-layer status matrix (shipped vs gap, with file locations); send-side two-publish design (Design B — keep instant receipt, add post-confirm republish with block+proof; dedupe by (txid, target)); receive-side fast-path with fall-through on proof failure (never hard-reject); phased delivery G.1–G.7 with effort estimates (~3–4 d after S1 ships and spec encoding lands). - Add the two new pending items to the existing "What's still pending" list to keep that section authoritative. quartz/plans/2026-05-08-local-headers-explorer.md — headers-explorer plan: - Rewrite §19 (follow-up onchain-zap verification) to reflect the spec change. Original section assumed we'd need BIP-37 merkleblock or full-block fetch over P2P; with the proof inline none of that infrastructure is required. Estimate collapses from 10–15 d to ~3–4 d. - Point §19 at the full implementation plan in the onchain-zaps file, keeping S1 focused on OTS while the follow-up details live with the rest of the NIP-BC work.
This commit is contained in:
@@ -853,29 +853,48 @@ a unit test for.
|
||||
|
||||
## 19. Follow-up: trustless NIP-BC onchain zap verification
|
||||
|
||||
*Not in this plan. Tracked here so the design choices above stay aligned.*
|
||||
*Not in this plan. Tracked here so the design choices above stay aligned.
|
||||
Full implementation plan lives in `amethyst/plans/2026-05-14-onchain-zaps.md`
|
||||
under "Inline SPV proofs (`block` + `proof` tags) — pending".*
|
||||
|
||||
The shipped `OnchainZapVerifier` (`quartz/.../nipBCOnchainZaps/verify/`)
|
||||
trusts `OnchainBackend.getTx(txid)` — i.e. Esplora — for both
|
||||
tx-existence-in-a-block and the output values used to compute
|
||||
`verifiedSats`. A malicious Esplora can fabricate or suppress zaps.
|
||||
### What the 2026-05-19 spec change buys us
|
||||
|
||||
Closing that gap is a **separate plan** that builds on this one:
|
||||
`nostr-protocol/nips#2332` adds optional `["block", "<hash>", "<height>"]`
|
||||
and `["proof", "<raw-tx-hex>", "<merkle-proof-hex>"]` tags on `kind:8333`.
|
||||
The proof rides inline in the Nostr event, so the trustless-verify path
|
||||
needs **no new P2P messages on top of S1** — no `getdata MSG_BLOCK`, no
|
||||
BIP-37 `filterload`, no full-block parser. Just header lookup + merkle
|
||||
walk against bytes already in the event.
|
||||
|
||||
- **Foundation reused:** `BitcoinPeer`, `PeerPool`, `HeaderStore`,
|
||||
`HeaderValidator`, `LocalHeadersBitcoinExplorer`.
|
||||
- **New work (rough ~10–15 days on top of S1):** BIP-37 `filterload` /
|
||||
`merkleblock` / matched-`tx` handling, or `getdata MSG_BLOCK` + stream
|
||||
parse; partial-merkle-tree verification; new `OnchainBackend` variant
|
||||
that asks the local stack for the inclusion proof and the matched tx
|
||||
while keeping Esplora for UTXO listing / broadcast / fee estimates on
|
||||
the *send* side.
|
||||
- **Net win:** zap-receive verification stops trusting Esplora. Zap-send
|
||||
still needs an address-indexed server (no headers-only equivalent
|
||||
exists), so that part of the trust story is unchanged.
|
||||
- **Filename:** `quartz/plans/YYYY-MM-DD-onchain-zap-merkle-proofs.md`,
|
||||
written once S1 has shipped and we have real numbers on first-run sync,
|
||||
store size, and battery cost.
|
||||
This collapses the original "follow-up plan" estimate from 10–15 days to
|
||||
**~3–4 days** of work after S1 ships and the spec's merkle-proof
|
||||
encoding is locked.
|
||||
|
||||
### Foundation reused from S1
|
||||
|
||||
- `LocalHeadersBitcoinExplorer.byHash(blockHash)` → validated header (for
|
||||
the `merkleRoot`).
|
||||
- `HeaderStore` for the by-hash index.
|
||||
- `LocalHeadersBitcoinExplorer.tipHeight()` for confirmation count.
|
||||
|
||||
### New work (in `nipBCOnchainZaps/`, not in `bitcoin/`)
|
||||
|
||||
- `MerkleProofVerifier.verify(txid, proofBytes, expectedMerkleRoot)` — small
|
||||
pure-function module. Test-vector-driven.
|
||||
- `OnchainZapVerifier` rewire to prefer the inline proof path when both
|
||||
tags are present; fall back to `backend.getTx` on absence or proof
|
||||
failure (never hard-reject).
|
||||
- `OnchainBackend.getMerkleProof(txid)` on the send side, plus a
|
||||
post-confirmation worker in `OnchainZapSender` that publishes a second
|
||||
`kind:8333` once the tx confirms, this time carrying `block` + `proof`.
|
||||
Receivers dedupe by `(txid, target)` preferring the variant with a
|
||||
valid SPV proof.
|
||||
|
||||
Detailed phase breakdown (G.1–G.7), gap matrix, and design rationale
|
||||
live in the onchain-zaps plan referenced above. The previous text of
|
||||
this section (BIP-37 / full-block / partial-merkle-tree options) is
|
||||
obsolete now that the proof is carried inline — kept in git history if
|
||||
anyone needs to revisit the assumption.
|
||||
|
||||
## 20. References
|
||||
|
||||
|
||||
Reference in New Issue
Block a user