— Security —

WHAT YOU'RE TRUSTING, AND WHY

The one-page version of docs/THREAT_MODEL.md -- stated in exactly the terms the underlying document uses, not softened for a marketing page.

The proof itself: trustless

A zkvm-stark proof — produced by prove_program, checked by verify_program — is a real STARK. Verifying it, whether locally via zkvm verify, over HTTP, or via the verify MCP tool, requires no trust in whoever generated it. This is standard, load-bearing cryptography: the test suite includes negative tests (rejects_tampered_result, rejects_tampered_program) confirming a proof manufactured for one claim is rejected against a different one.

This is the only trustless part of the system end to end.

The on-chain path: an attested bridge, not a cryptographic verifier

ProofOrchestrator pays a prover once a proof is "accepted," and what "accepted" means depends entirely on which IProofVerifier it's configured with:

  • UnimplementedStarkVerifier — accepts nothing. Every submitProof call reverts. No trust required, because no payment is possible.
  • AttestedVerifier (the one scripts/onchain_demo.sh uses) — accepts a proof once a designated attester address calls attest(publicInputsHash, proofHash).

Concretely, the trust assumption is: the attester key is not compromised, and whoever controls it always verifies locally before attesting, never on faith. If that fails — key theft, or a careless/malicious attester — a false attestation pays out a real reward for a proof that either doesn't exist or doesn't verify. The contract has no way to detect this; it only checks that the attester's signature is present, not that the underlying math is sound.

This is the same trust model a centralized sequencer has before its fraud/validity proofs go live: a known, single point of trust, acceptable because it's explicit and small, not because it's absent.

Key management, honestly

There is currently no key management story beyond "a private key exists and someone runs cast send ... --private-key." Concretely, for anything beyond a local demo:

  • The attester key should never be the same key used for anything else — a compromise of one shouldn't compromise the other.
  • It should live in whatever secrets store the deployment environment already has — scripts/onchain_demo.sh's hardcoded Anvil test keys are demo-only.
  • Rotation means deploying a new AttestedVerifier with the new attester address — there's no in-place key-rotation function.

None of this is implemented. It's written here so the gap is a documented decision, not a silent omission.

When does this stop being true?

Only when a real cryptographic verifier replaces AttestedVerifier — see the On-Chain Verifier page for exactly what that requires. Until then, "the proof is trustless, the payment is not" is the accurate description of this system, stated in exactly those terms.