Three backends, same interface

BitcoinPIR ships three interchangeable PIR backends behind a single client API. Same inputs, same outputs — different assumptions about how privacy is enforced and how the compute / bandwidth budget is spent.

2 servers non-colluding

DPF-PIR

Distributed Point Functions. The client splits its query into two additive shares and sends one to each server. XOR the two responses on return; everything cancels except the target row. Small queries, fast online round; assumes the two servers don't collude.

1 server FHE

OnionPIR

LWE-based single-server PIR. The query is a homomorphically encrypted selector; the server computes sum(encrypted_selector · row) over the whole DB and returns an encrypted result. No non-collusion assumption — at the cost of heavier compute per query.

1 server stateful

HarmonyPIR

Single-server stateful PIR. In a one-time offline phase the client streams the whole database and condenses it into √N-size hints. Each online query is then just a small batch of plain database indices whose privacy comes from a private random permutation over the hints; combining the response with a local hint recovers the row.

All three share the same upstream plumbing: the same cuckoo layout, the same padding discipline, the same Merkle-verified responses. We'll work through those shared pieces one at a time, then come back to see how they snap together end-to-end.