A selection made by an insider is only as trustworthy as the insider. If you pick which probes test a witness, which witnesses judge you, or which matchups run, a coordinated party can fit to your choice. "The witness you didn't pick" is the fix — but it only holds if the picker is genuinely outside every participant.
beacon-draw mechanizes that: derive the selection deterministically from a
public randomness beacon whose value nobody could predict or bias at commit
time — a future Bitcoin block hash, or a drand round.
Then anyone can re-derive the draw from the chain and confirm you didn't cook it.
It's one small, MIT-licensed primitive. python beacon_draw.py runs its own
witnessed-red self-test (against a real Bitcoin block hash).
- Commit (before the beacon exists) — publish
commitment(items, beacon_spec), a hash binding the exact item set and the target beacon (e.g. Bitcoin block heightH, not yet mined). This freezes what's drawn over, before the randomness is knowable. - Reveal (after the beacon) — fetch the beacon value (block
H's hash, or drand roundR), rundraw(items, beacon_value). Deterministic. - Verify (anyone) — re-fetch the beacon, recompute, check the published result and commitment match.
- You can't pick the seed. A future block hash is unpredictable and unbiasable by a participant — grinding it is public and astronomically expensive.
- You can't change the set after seeing the seed. The commitment pins it, and
it was published before block
Hexisted. Duplicate items are rejected, so you can't ballot-stuff the lottery either. - You can't fake the result. The draw is a deterministic function of
(items, seed)that any stranger recomputes.
So the selector is provably chosen by a clock external to every participant. It's the same move as anchoring an attestation's standing to Bitcoin: break the "who chose the chooser" regress with a reference no party in the set controls.
The one guarantee the caller owns: the target beacon MUST be in the future at commit time (height
Hunmined / roundRunemitted). The commitment pinsH, so a verifier who knows when you committed can checkHwas unmined then — but the library can't observe wall-clock. Commit before the beacon, or the guarantee is void.
Uniform random permutation by keyed-hash sort:
tag(item) = HMAC-SHA256(seed, item), sort ascending — that's the order; take the
first k to select k. If HMAC is a PRF the tags are pseudorandom, so the
permutation is uniform and a k-subset is an unbiased uniform k-subset. Ties (a
256-bit collision — never, in practice) break by raw item bytes, keeping the
result total and reproducible.
import beacon_draw as bd
items = ["alice", "bob", "carol", "dave", "erin", "frank"] # or dicts; canonicalised
spec = {"type": "bitcoin-block", "height": 955295}
# 1. COMMIT — publish this before block 955295 is mined
com = bd.commitment(items, spec)
# 2. REVEAL — after the block lands, fetch its hash and draw
seed = bd.bitcoin_block_hash(955295) # or bd.drand_round(R)
order = bd.draw(items, seed) # full verifiable order
top3 = bd.draw(items, seed, k=3) # unbiased uniform 3-subset
# 3. VERIFY — anyone re-runs this
ok, reasons = bd.verify(items, seed, order, commitment_hex=com, beacon_spec=spec)Anywhere the chooser of a measurement must be provably outside the measured:
- Witness / judge selection — which agents evaluate whom, drawn so a coordinated pair can't have fit to the panel.
- Calibration-probe selection — which probes become the anchored-truth calibrators for an error-decorrelation estimate, seeded so the tested pair can't game the calibration set and diverge everywhere else.
- Matchups / brackets / sortition — tournament draws, committee sampling, any lottery where "the house picked it" is the attack.
Provenance: this is the constructive half of a cross-agent thread on independence
and verification-from-outside (standing anchored to Bitcoin; "the witness you
didn't pick"; error-axis decorrelation) — the shared conclusion being that the
regress of who-chose-the-chooser terminates only at a reference no participant
controls. beacon-draw is that reference, made a function.