30817:nip-333-bitcoin-block-headers
NIP-333: Bitcoin Block Headers
draft optional
Canonical copy: https://nip-333.github.io/spec/ · source: https://github.com/nip-333/nip-333.github.io/blob/gh-pages/spec/nip-333.md
This NIP defines a protocol for distributing Bitcoin block headers over Nostr.
Abstract
Bitcoin block headers are 80-byte cryptographic proofs. This specification defines a minimal, self-contained event for publishing the latest 12 headers via Nostr. The event includes URLs to additional data sources, enabling clients to bootstrap and sync the full header chain.
Event Format
Kind
33333
A parameterized replaceable event (30000-39999 range). Relays store only the latest version for each (pubkey, kind, d-tag) combination. The d tag is the network code, so each network is its own replaceable stream — one publisher key can serve several networks without overwriting itself.
Tags
| Tag | Required | Description |
|---|---|---|
d |
Yes | Network stream identifier: btc, tbtc3, or tbtc4 — MUST equal the n tag |
n |
Yes | Network: btc, tbtc3, or tbtc4 |
tip |
Recommended | Chain tip height (last header in content) |
u |
Recommended | Data source URL |
p |
Optional | Other trusted publisher pubkey |
alt |
Recommended | Human-readable description per NIP-31 |
Note: tip is recommended but optional — clients can derive height from header chain validation.
Legacy d: latest: earlier drafts of this NIP used d: latest for all networks. Because relays replace on (pubkey, kind, d), a single key publishing two networks would overwrite its own stream. During migration clients MAY query "#d": ["btc", "latest"] and keep the newest verified event.
Networks
| Value | Network |
|---|---|
btc |
Bitcoin mainnet |
tbtc3 |
Testnet3 |
tbtc4 |
Testnet4 |
Content
Exactly 12 concatenated Bitcoin block headers encoded as lowercase hexadecimal:
length = 12 headers × 80 bytes × 2 = 1,920 characters
Headers in ascending order. The 12th header is the chain tip. First header height = tip - 11.
Example Event
{
"kind": 33333,
"pubkey": "cccccccc829b802b7bf52d43edf7cfe62ac89f332a318b6826ac8bd6e73660da",
"created_at": 1733356800,
"tags": [
["d", "btc"],
["n", "btc"],
["tip", "875011"],
["u", "https://github.com/bitcoincc/bitcoin-epochs/releases/latest/download/btc.archive.bin"],
["u", "https://github.com/bitcoincc/bitcoin-current/releases/latest/download/btc.current.bin"],
["p", "deadbeef1234567890abcdef1234567890abcdef1234567890abcdef12345678"],
["alt", "Bitcoin headers 875000-875011"]
],
"content": "00e0ff3f...[1920 hex chars]...",
"id": "...",
"sig": "..."
}
Data Sources
The u tag points to header archive files. Two files provide complete coverage:
| File | Contents |
|---|---|
{network}.archive.bin |
All completed epochs (immutable, grows each epoch) |
{network}.current.bin |
Current epoch in progress (up to 2016 headers) |
The NIP-333 event itself provides the chain tip (latest 12 headers).
URL Schemes
The u tag accepts standard URL schemes:
https://— Remote HTTP(S) resourcesfile://— Local filesystem paths
Clients SHOULD try URLs in tag order, preferring faster sources. Common local paths include ~/.spv/{network}.archive.bin and ~/.spv/{network}.current.bin for offline operation and reduced bandwidth usage.
Sync Strategy
1. Subscribe to kind:33333 → get tip (12 headers)
↓
2. GET btc.current.bin → current epoch
↓
3. GET btc.archive.bin → completed epochs (background)
↓
4. Stay subscribed for new blocks
Clients validate that headers chain together. If a gap exists between current.bin and the nostr tip, refetch current.bin.
Discovery
utags — Data source URLs (preferred, follow-your-nose)ptags — Other trusted publishersdid:nostr— Optional identity via did:nostr
Header Structure
Each 80-byte Bitcoin block header:
| Field | Bytes | Offset | Description |
|---|---|---|---|
| Version | 4 | 0 | Block version (little-endian) |
| Previous Hash | 32 | 4 | Hash of previous block |
| Merkle Root | 32 | 36 | Transaction merkle root |
| Timestamp | 4 | 68 | Unix timestamp |
| Bits | 4 | 72 | Difficulty target (compact) |
| Nonce | 4 | 76 | Proof-of-work nonce |
Subscription
["REQ", "headers", {
"kinds": [33333],
"authors": ["cccccccc829b802b7bf52d43edf7cfe62ac89f332a318b6826ac8bd6e73660da"],
"#d": ["btc"],
"limit": 1
}]
Verification
Clients SHOULD verify:
- Signature — Event signed by trusted pubkey
- Length — Exactly 1,920 hex characters (12 headers)
- Chain — Each
prevHashlinks to previous header's hash - Proof-of-work — Header hashes meet difficulty targets
Security Considerations
- Trust: Only subscribe to known, reputable publishers
- Cross-reference: Compare tips from multiple
ptag publishers - Relay diversity: Use multiple relays for redundancy
- Source verification: Validate data from
utag sources
Compact Clients
This NIP supports the Compact Client (CC) framework:
| Level | Description |
|---|---|
| CC/0 | SPV — Headers + merkle proofs |
| CC/1 | Verify-don't-serve — Full validation via proofs |
| CC/2 | ZK-verified — Zero-knowledge proofs (future) |
Implementation
Parsing Headers
function parseHeader(hex, index) {
const offset = index * 160;
const headerHex = hex.slice(offset, offset + 160);
const bytes = new Uint8Array(80);
for (let i = 0; i < 80; i++) {
bytes[i] = parseInt(headerHex.slice(i * 2, i * 2 + 2), 16);
}
const view = new DataView(bytes.buffer);
return {
version: view.getUint32(0, true),
prevHash: bytesToHex(bytes.slice(4, 36).reverse()),
merkleRoot: bytesToHex(bytes.slice(36, 68).reverse()),
timestamp: view.getUint32(68, true),
bits: view.getUint32(72, true),
nonce: view.getUint32(76, true)
};
}
Computing Header Hash
async function computeHeaderHash(headerHex) {
const bytes = hexToBytes(headerHex);
const hash1 = await crypto.subtle.digest('SHA-256', bytes);
const hash2 = await crypto.subtle.digest('SHA-256', hash1);
return bytesToHex(new Uint8Array(hash2).reverse());
}
References
- NIP-01: Basic Protocol Flow
- NIP-31: Dealing with Unknown Event Kinds
- did:nostr Method Specification
- Electrum Protocol
- bitcoin.cc — Reference implementation
Cited links
nip-333.github.io
NIP-333 Specification
github.com
nip-333.github.io/spec/nip-333.md at gh-pages · nip-333/nip-333.github.io
NIP-333: Bitcoin Block Headers over Nostr. Contribute to nip-333/nip-333.github.io development by creating an account on GitHub.
nostrcg.github.io
Nostr DID Method Specification
electrumx.readthedocs.io
Protocol Methods — ElectrumX ElectrumX 1.20.2 documentation
bitcoin.cc
bitcoin.cc - Compact Clients
Compact Clients for Bitcoin. Full verification, minimal footprint.
Discussion
Connect a key to comment.