Cuckoo hashing — two levels of it

BitcoinPIR uses cuckoo hashing at two different levels, and they do different jobs. Mixing them up will make the later sections confusing, so here's the distinction up front.

Level 1: PBC group assignment (3 candidate groups)

Each scripthash gets mapped to 3 candidate PBC groups (Probabilistic Batch Code) — out of K=75 groups for the INDEX table and K_CHUNK=80 for CHUNK. This is how the database is batched: the server can answer many parallel PIR queries in one round, as long as each real query lands in a different group.

// pir-core/src/params.rs:89
num_hashes: 3,    // each item → 3 candidate PBC groups

Level 2: In-group cuckoo table (2 hash functions)

Once an item is placed in one of its 3 candidate groups, it lives inside that group's own cuckoo hash table. The in-group table uses 2 hash functions — so an item has exactly 2 possible bin positions inside its group, with slots_per_bin slots per bin (4 for INDEX, 3 for CHUNK).

// pir-core/src/params.rs:92
cuckoo_num_hashes: 2,   // each item → 2 bins in its group
scripthash 76a9…ab PBC groups (K = 75) g0 g1 g2 g3 g4 g5 g6 g7 g8 g9 g10 g11 g12 g13 g14 … and 60 more inside group g₈ bin h₀ bin h₁ slot 2 of h₀ contains the item
A scripthash derives 3 candidate PBC groups. Placement picks one; inside that group, cuckoo hashing picks one of 2 bins.