Skip to content

About

Implementing PIR for Bitcoin UTXO set

Resources

Security policy

Stars

16 stars

Watchers

1 watching

Forks

Repository files navigation

Bitcoin PIR — Private Bitcoin Wallet Lookups

Query the Bitcoin UTXO set without revealing which addresses you're interested in.

Today's light wallets leak every address you own to their server, enabling full surveillance of your balances, transactions, and spending habits. Bitcoin PIR uses Private Information Retrieval — a family of cryptographic protocols where the server(s) provably learn nothing about which records you look up — to give light wallets the same privacy as a full node, without the storage cost.

Try It

A live demo runs at https://app.bitcoinpir.org/. You can paste any Bitcoin address in the browser and watch it resolve to UTXOs privately. OnionPIR and Direct ORAM each need one server; DPF-PIR and HarmonyPIR also need a second server, which the demo runs on a home machine on a best-effort basis, so it may be offline. The first query may be slow — please be patient.

What It Does

  • Look up any Bitcoin address privately — balance, UTXOs, and transaction history, with zero leakage to the server
  • Batch many addresses at once — wallet sync performs dozens of lookups in a single round
  • Verify results cryptographically — each result comes with an optional Merkle proof tying it to the database's Merkle root; together with remote attestation of the server binary, this stops a malicious server from silently returning wrong data (the proof alone establishes consistency with a server-supplied root — see the trust-model note under "Key Features")
  • Four privacy backends in two tiers for different trust and performance trade-offs (one server or two; see below)
  • Works with existing wallets via plugins and adapters — no need to build a wallet from scratch

Privacy Backends

You can pick the backend that matches your threat model and performance needs. OnionPIR and Direct ORAM are the supported backends; each needs one server. DPF-PIR and HarmonyPIR are optional backends that need a second, independent server.

Backend Trust Model Best For
OnionPIR (1-server, FHE) Single server, cryptographic privacy from lattice hardness Strongest single-server guarantee
Direct ORAM (1-server, TEE) Trusts AMD SEV-SNP: queries reach an attested server over an encrypted channel, and ORAM hides the server's access pattern from its host Low-cost single-server lookups
DPF (2-server) Privacy holds as long as two servers don't collude Fast, lightweight queries
HarmonyPIR (1 or 2-server, stateful) Offline setup phase; deployed here as 2-server (query server + dedicated hint server) Fast online queries after initial sync

DPF-PIR, HarmonyPIR and OnionPIR implement the same Rust PirClient trait (connect, catalog, sync), so a client can switch between them without changing its code. Direct ORAM has its own OramClient: the caller attests the server and upgrades to the encrypted channel before any lookup.

Supported Wallets and Clients

Bitcoin PIR plugs into the existing Bitcoin ecosystem rather than replacing it:

  • Web browser — a TypeScript + WASM client runs entirely in-browser, no extension needed
  • Rust CLI — a reference command-line client for testing and scripting

Wallet-library integration (BDK) is a possible future direction; earlier adapter experiments (an Electrum plugin, a bitcoinjs explorer adapter) were removed in 2026-08 after falling behind the protocol.

Key Features

Cryptographic result verification

Each UTXO lookup can be paired with a Merkle proof query that checks the result against the database's Merkle root. Verification is batched across all addresses in a wallet sync — one proof round covers the whole batch. The server can refuse to answer, but it cannot return data that contradicts the root it committed to; whether that root itself can be trusted is an attestation question — see the trust-model note below.

Trust-model note on Merkle verification. Clients check each result's Merkle proof and report the verdict per result (merkleVerified); the caller decides what to do with an unverified one. A client can also verify the database proof, install the roots it returns, and have the tree-tops checked against the attested database super-root before querying; the production web client does this for DPF, HarmonyPIR, and standalone OnionPIR, comparing each proof with its production pin. OnionPIR uses the attested onion_super_root; its server-info.super_root is diagnostic only. On the Direct ORAM host, runtime integrity is backed by SEV-SNP and a verified AMD VCEK chain. pir1 (Hetzner) and pir2 (a MacBook) have no TEE, so their tier is operator identity plus binary pinning, not hardware attestation. See the database/root rotation runbook.

Privacy note on Merkle verification. Within each PIR round, queries are padded to a fixed count (75 for index, 80 for chunk) so the server cannot tell which group is real. Every query — found, not-found, or whale — performs at least one CHUNK PIR round and at least one CHUNK-Merkle sibling pass, so a not-found query stays indistinguishable from a found one (the round-presence invariant). INDEX Merkle items are distributed across PBC groups so the per-level sibling-pass count does not depend on a batch's collision pattern (INDEX Merkle Group-Symmetry). Trade-off (2026-05-17): the three PIR backends (DPF, HarmonyPIR, OnionPIR) no longer pad each query's CHUNK Merkle items to a fixed M = 16; a query now fetches and verifies its real chunk count, so the server learns the approximate UTXO count of a found address. This is an admitted leak — mild for the ~99% of addresses with a single chunk. See docs/VERIFICATION_OVERVIEW.md for the full picture.

Batch queries

Wallet sync typically touches dozens of addresses at once. Bitcoin PIR packs multiple addresses into a single PIR round using probabilistic batch codes, so syncing a wallet with 50 addresses takes roughly the same time as syncing one.

Full UTXO dataset

The server hosts the complete Bitcoin UTXO set (~815K active script types at time of writing), filtered to exclude dust and very heavy addresses. Light wallets see the same data a full node would return.

Open and self-hostable

Anyone can run a node serving the published database generation (docs/OPERATOR_GUIDE.md). Free queries are open; a provider chooses per backend what is free, paid, or free while the server has room, and paid queries present credits verified at an issuer (docs/CREDITS.md) without giving the PIR host any payment secret. No payment gate is enabled by merely building this repository.

Project Layout

BitcoinPIR/
├── crates/
│   ├── protocol/      Shared database, channel, and server-runtime primitives
│   ├── sdk/           Rust core, native-client, and WASM SDK crates
│   ├── trust/         Identity, attestation, and database-proof verification
│   └── directory/     Nostr service-directory codec (provider discovery)
├── apps/
│   ├── server/        Production server and diagnostic binaries
│   ├── directory-relay/  Directory-only Nostr relay (provider discovery)
│   └── admin/         Operator CLI
├── tools/
│   └── db-builder/    Database generation pipeline
├── web/               Production browser query application
├── deploy/            Reproducible build and deployment integration
└── docs/              Design, verification, and operating documentation

Production diagnosis starts at docs/PRODUCTION_OPERATIONS.md. Database and Direct ORAM source/intermediate retention is mapped in docs/DATABASE_ARTIFACT_RETENTION.md; consult it before deleting artifacts or starting an expensive rebuild.

Reusable protocols, formal proofs, generated proof bundles, demos, and research sources live in separate repositories under the Bitcoin-PIR organization; see docs/REPOSITORY_BOUNDARIES.md.

Getting Started

  1. Clone and build:
    git clone https://github.com/Bitcoin-PIR/Bitcoin-PIR.git
    cd Bitcoin-PIR && cargo build --release
  2. Point clients at the live demo servers (no database build needed) — see web/ for the browser client.
  3. Or run your own node: docs/OPERATOR_GUIDE.md. For development, scripts/build_full.sh builds databases from a Bitcoin Core UTXO snapshot (a few hours) and scripts/start_pir_servers.sh serves them; their proofs do not match the production clients' pins.

For development, see docs/TESTING.md.

Documentation

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Contributing

Contributions are welcome — please open a pull request or issue.

About

Implementing PIR for Bitcoin UTXO set

Resources

Security policy

Stars

16 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages