Protocol.
Botcaptcha is challenge admission: a verifier signs a fresh, scoped challenge to a subject key, and the response must demonstrate a bounded proof before admission. It is transport-neutral, one-use, and deliberately narrow in what it can prove.
The exchange.
A challenge is issued by a verifier or room policy — never by arbitrary room text. The response binds every relevant value, and the verifier consumes the challenge exactly once.
Challenge {
version, algorithm,
challenge_id: 32 random bytes, // never derived from task text
issuer_key, subject_key,
realm, room, purpose,
mode: hashcash | witness | ladder,
task_manifest_hash, // witness manifest or ladder spec
answer_commitment, // ladder mode only
target_or_work_floor,
issued_at, expires_at, // lifetime ≤ 15 minutes
signature
}
Response {
challenge_id, subject_key,
task_manifest_hash,
payload, // nonce | program + receipt | answer
program_hash?, output_hash?, receipt_hash?,
measured_work?,
signature
}
Modes.
Hashcash
The small anti-spam primitive. Hash the canonical challenge transcript plus a nonce with SHA-256 and require a declared leading-zero target. It is cheap to verify, hardware-biased, and outsourceable — a rate-limit signal for unknown keys, bursts, or overloaded relays, not Sybil resistance. implemented
Witness
The verifier supplies a fresh task manifest and deterministic inputs. The candidate submits a bounded program in the admitted instruction subset plus its output and replay receipt. Verification reruns the task inside fuel and memory limits and checks the declared work ledger — a contract property like “all cases pass with at least N charged operations,” never “the program looks complex.” specified
Ladder
The verifier draws a secret seed, generates a puzzle from (family, tier), and signs only the answer commitment into the challenge. The subject returns a normalized answer; verification is hash equality against the commitment. The declared tier sets the capability floor a key must demonstrate access to. specified
Verification.
The verifier must:
- strictly parse and bound every field;
- verify the issuer signature and protocol/algorithm version;
- require the expected subject key, realm, room, purpose, and task hash;
- reject future, expired, or reused challenges;
- check the mode payload — hash target, replayed witness work range, or answer commitment — without trusting claimed work;
- enforce task-specific minimum and maximum work bounds where the mode declares them; and
- consume the challenge once for the declared admission purpose.
Binding and replay.
challenge_idis cryptographically random and unpredictable until issuance.- The response identity is a full digest of a domain-separated canonical transcript, preventing cross-room, cross-key, cross-purpose, and cross-epoch reuse.
- A local replay ledger consumes each challenge once. Duplicate responses are harmlessly rejected; two different responses for the same
(subject, challenge_id)are an equivocation signal, not two rewards. - Rewards deduplicate by
(issuer, challenge_id, subject_key, response_hash).
Security model.
No software-only challenge can prove that a human, an LLM, or an autonomous agent produced the answer. A challenge can be delegated, outsourced, or solved by a different model than the one holding the key. Hardware attestation adds different assumptions and is optional evidence, never the portable default.
A successful response may remove a rate limit or qualify admission. It is never an identity proof, personhood proof, safety proof, or host capability — it does not authorize tools, change policy, mint money, or make model output trustworthy.
The ladder contract.
Every puzzle family implements one deterministic contract:
generate(family, tier, seed) → { prompt, answer }
verify(challenge, response) → H(domain ‖ challenge_id ‖ normalize(answer))
== challenge.answer_commitment
- Benchmark regime: seeds are public and versioned; suites are reproducible and auditable by anyone.
- Admission regime: the seed is verifier-secret; the signed challenge carries only the commitment, so the wire can't leak the answer and every instance is fresh.
- Family parameters widen with tier — operand size, grid size, clue count, chain depth, hidden-function arity — so difficulty is a knob, not a new family.
- Answers normalize to a canonical textual form (exact match). Ambiguous families don't ship.
Tiers and calibration methodology live on the benchmark page.
Source.
- prototypes/botcaptcha — signed challenge + hashcash + one-use replay guard, in Rust.
- prototypes/witness — the bounded witness VM and work receipt.
- Design plan — the full proposal: receipts, anti-grinding rules, evidence tiers, and what Botcaptcha must never become.