Field SOP
Field SOP

17 Seconds on a CPU: Prove Which Model Answered You

Verify the cryptographic birth certificate of an AI reply on a plain CPU with the open-source FlashProve from Anthropic: prepare Linux (g++ 13 or later, non-root, under 2GB RAM; WSL2 as the common Windows route), clone anthropics/FlashProve (0.16.0), build with verifier/build.sh in one to two minutes, run the stored example under examples/accepted-proof (expect a final line YES, exit code 0, under 2 seconds), read results via the exit-code table (0 accepted, 1 rejected, 5 unchecked, 14 invalid call), then the real-world five-argument call and the rule that the commitment ID must come from a trusted third party. Honest limits throughout: it proves provenance not correctness, a 1024-token context, officially not maintained, and no major provider ships proofs yet.

Published November 5, 20269 min read
<!-- flashprove-proof-verify-sop | sop | 17 Seconds on a CPU: Prove Which Model Answered You -->

When you pay for a hosted model, a second bill hides behind the token count: is the model you bought actually the one answering? Rumors of relay providers swapping in a cheaper model never quite go away, and the only honest response used to be local deployment. FlashProve offers a third option: the provider publishes a commitment ID that binds it to one set of weights, every reply ships with a cryptographic proof, and anyone with an ordinary CPU can run cp_verify for a few seconds to confirm the answer really came from the committed model, without ever touching the weights. The repository is anthropics/FlashProve, currently at version 0.16.0, Apache-2.0 licensed, self-described as a research artifact: not maintained, not accepting contributions.

First, the boundaries. The companion open-source piece in this batch (/en/posts/flashprove-verifiable-inference-opensource-resource) covers what FlashProve is and why it is trustworthy: the soundness theorem written in Lean 4, the commit-prove-verify protocol, and what it means for API honesty. That is the theory layer. This article is the hands-on SOP and solves one problem only: getting the verifier running on your machine, from environment setup through cloning and building cp_verify, then verifying a stored proof, reading exit codes, and finally the five-piece calling convention for real-world proofs. Wiring an API into your scripts is a different job, covered by the Hy4 integration SOP (/en/posts/hy4-tokenhub-api-integration-sop). All commands follow the README verbatim, captured on November 5, 2026.

Before you start: four routes and one bucket of cold water

The README splits the work into four routes by hardware, so lay out the map first and decide how far you go. Route 1 builds cp_verify and checks a stored proof; it needs Linux, bash, g++ 13 or later, and under 2 GB of RAM, with a build of 1 to 2 minutes and a single check in under 2 seconds. That route is the backbone of this article. Route 2, toy proofs, is a CPU self-test of the proof library; it adds make and python3, stays under 1.5 GB of RAM, and finishes in about 1 minute. Route 3 builds the prover on a GPU and runs an 8-layer synthetic model, which takes an H100 plus a full GPU stack and a build of about 29 minutes; at full size it wants 280 GB of RAM and about 42 minutes. Route 4 downloads a 232 GB public 4-bit conversion and proves a token against the real Llama 4 Maverick weights, which means 330 GB of RAM and hours. A reasonable stopping point is route 2; this article only writes down the entry bar for the rest.

One official figure is worth memorizing: verifying a full real-world proof takes about 17 seconds on a 24-thread CPU, while the stored example in step four checks in under 2 seconds. A real proof covers the whole inference over a 1,024-token context window; the example is a minimal payload. That number is why ordinary auditing is suddenly realistic: no GPU, an old laptop works as the verification machine.

Now the cold water. As of November 5, 2026, no mainstream provider ships FlashProve proofs in production. Do not take this article and try to verify a production OpenAI or Anthropic API; that path does not exist today, and this article will not invent one. The value here is readiness: the verifier builds, the principles are understood, and the exit codes are readable. The day any provider ships proofs, you can audit them the same day.

Step 1: Environment setup, lower than you expect

The hard requirements are four: x86-64 Linux, bash, g++ 13 or later, and under 2 GB of RAM. The last one looks like a typo on first reading. Most inference frameworks demand dozens of gigabytes of VRAM or memory; FlashProve squeezed its verification side under 2 GB, the payoff of a design where proofs are generated on expensive provider hardware and checked cheaply everywhere else. Check memory with free -h and the compiler with g++ --version; below 13, upgrade first.

Treat the permission rules as iron law. Every command runs as an ordinary (non-root) user from the repository root, never as root or under sudo; only installing system packages needs root. The rules for coding agents are blunter: never get past an error with sudo, chmod, chown, rm, or by editing a source file; stop and report. Humans benefit from the same discipline, because a build pushed through with forced permissions only postpones the failure.

Windows users: the native environment is not supported. The common workaround is running everything inside a WSL2 Linux distribution; note plainly that this is community convention, not README text. The supported list contains only x86-64 Linux, and macOS is also outside it. On a minimal Ubuntu 24.04, the dependencies for routes 1 and 2 are one line, which needs root:

bash
apt-get update && apt-get install -y --no-install-recommends g++ make python3 unzip

make and python3 are only needed for route 2; for the backbone of this article, g++ and unzip are enough. The g++ 13 line bites: Ubuntu 24.04's default repositories satisfy it, while Ubuntu 22.04 ships g++ 11, and getting to 13 requires a newer toolchain source, an operation the README does not cover.

Step 2: Clone the repository and learn three locations

Every command from here on assumes you are in the repository root:

bash
git clone https://github.com/anthropics/FlashProve
cd FlashProve

After cloning, learn three locations. verifier/ is the protagonist: the verifier source and build.sh live there. examples/accepted-proof/ holds a stored proof known to be accepted: config, ivk, example.req, example.y, example.proof, plus ID.txt with the commitment ID; step four verifies exactly this set. guide/ and docs/ hold the documentation, and the procedure for constructing a request file lives in guide/verify-a-proof.md. The current version is 0.16.0, and the README states the artifact status plainly: not maintained, not accepting contributions, Apache-2.0. In practice that means issues are not triaged, so problems are yours to solve against the documentation; the upside is a protocol and documentation that move together, so following the README almost never meets version drift.

Step 3: Build the verifier, one to two quiet minutes

The build is a single line:

bash
verifier/build.sh

Its behavior is unusual. It stays silent for 1 to 2 minutes with no progress output, then prints a line starting with THE VERIFIER IS BUILT: and ends with exit code 0. The silence is not a hang; it is the documented behavior. Any line starting with build.sh: note: is a warning rather than an error, quoted verbatim when reporting. If your terminal tool calls time out, the README provides a background-build one-liner:

bash
echo "build started" >> verifier-build.log; nohup bash -c 'verifier/build.sh; echo "exit code $?"' >> verifier-build.log 2>&1 &

Then poll the log:

bash
tail -n 2 verifier-build.log

until the last line starts with exit code. The README adds one explicit warning: do not start a second build while the first runs. Common build failures trace back to two causes: a g++ older than 13, and permission confusion from reflexive sudo, leaving artifacts owned by root so every later step fails in a chain. Rebuilding cleanly under the non-root discipline costs less than patching the mess.

Step 4: Verify the stored proof and see YES

Once the build succeeds, cp_verify appears under bin/. Run it on the stored example with the command exactly as the README gives it:

bash
bin/cp_verify examples/accepted-proof/config examples/accepted-proof/ivk examples/accepted-proof/example.req examples/accepted-proof/example.y examples/accepted-proof/example.proof -id "$(cat examples/accepted-proof/ID.txt)"

Two expected results, both must hold: the last line is YES and the exit code is 0. Be precise about what YES proves. The README's own sentence: this example is a small model with synthetic weights, so it shows only that the verifier works, not anything about a served model. YES certifies that the protocol implementation runs on your machine and the verifier is installed correctly; it is not a verification of any provider. Treat it as a thermometer self-test, not a medical report.

Step 5: Read the exit codes and meet the real-world five pieces

The stored example is a warm-up. A real-world call has five pieces:

text
bin/cp_verify CONFIG_DIR PUBLIC_KEY_DIR REQUEST_FILE TOKEN_FILE PROOF_FILE -id COMMITMENT_ID

Five files and one ID. CONFIG_DIR and PUBLIC_KEY_DIR come from the provider's published configuration and public keys. REQUEST_FILE is the request file you construct yourself, following guide/verify-a-proof.md. TOKEN_FILE is the reply being verified, PROOF_FILE is the proof that shipped with it, and COMMITMENT_ID is the commitment ID the provider published. Read the result from the exit code and the last line together. The exit code table from the verifier documentation follows, numbers copied exactly:

ExitLast lineMeaning
0YES / WITHIN LIMITS: ...Accepted: exact match, or within the clipped gap
1NO: <name>Rejected, or a local fault
5NOT CHECKED: <name>No verdict; retry once only for internal-stage or internal-exception-parFor
14NOT-A-VERIFICATIONThe call itself was invalid; see the lines after ---- the call ----
2, 3, 4, 15(not fixed)Bad command line or file, or a partial call; no verdict

Three reading disciplines deserve a permanent comment in your verification scripts. First, the retry window for exit code 5 is narrow: only when the name in the last line is internal-stage or internal-exception-parFor may you retry once; any other NOT CHECKED goes straight to a report. Second, exit code 1 is ambiguous: the proof may genuinely be rejected, or your local environment may be missing a file; rule out your own side before announcing that the provider cheated. Third, exit code 14 means your call was malformed, not that the provider did something wrong; read the lines after ---- the call ----.

The most dangerous trap in real-world verification is the source of the commitment ID. The security model rests on one asymmetric rule: get it from a party you trust, never from the server being checked or from files sent along with the proof. If the ID comes from the verified party itself, that party can swap the weights, mint a new ID, and reissue proofs, and your verification loses its anchor. The stored examples are the only exception. Separately, the official integrations/ directory provides check_proof.py, a wrapper that bundles the call and the result comparisons, suited to automated pipelines.

The boundary list: YES does not mean the answer is correct

Close with the protocol's boundaries so a YES is never over-trusted. First, FlashProve proves provenance, not correctness: the proof says the reply came from the committed weights, and says nothing about whether the content is right or useful. Second, the covered context window is 1024 tokens; anything beyond is outside the commitment. Third, the protocol assumes a deterministic inference process, with integerized arithmetic and greedy MoE routing among its preconditions; details live in the repository's limits documents. Fourth, the repository is not maintained and accepts no contributions; the code is a research artifact under Apache-2.0, with licensing details in LICENSE, NOTICE, and THIRD_PARTY.md. Fifth, and most important: no mainstream provider ships proofs in production today. The goal of this article was never to let you audit a commercial API this afternoon; it is to leave your verifier built and your five-piece call rehearsed.

For one step further: route 2's toy proofs run on CPU in about a minute, and the expected output has the third line from the end starting with AS EXPECTED: the honest copy was accepted, showing the honest copy accepted and the cheating copy rejected side by side. Routes 3 and 4 need an H100 and the full GPU stack (CUDA 13.2 Update 2, nvcc 13.2.86); the memory and time bars are in the route table above. The theory layer, including the Lean 4 theorem, lives in the open-source companion piece (/en/posts/flashprove-verifiable-inference-opensource-resource); the road that does require watching VRAM is local deployment, covered by the local deployment SOP (/en/posts/llm-local-deploy-vram-sop).

FAQ

Q1: Can I run cp_verify on Windows directly? A1: No. The README supports x86-64 Linux only, with bash and g++ 13 or later required. The common workaround is running the steps inside a WSL2 Linux distribution; note that this is community convention rather than README text. macOS is also outside the supported list.

Q2: build.sh prints nothing for a long time. Is it stuck? A2: No. The README documents 1 to 2 minutes of silence, then a line starting with THE VERIFIER IS BUILT: and an exit code of 0. Lines starting with build.sh: note: are warnings, not errors. If your terminal times out, use the background build one-liner and poll tail -n 2 verifier-build.log until the exit code line appears, without starting a second build.

Q3: What does YES prove, and what does it not prove? A3: It proves the verifier works and that this stored proof passes the protocol check. The example uses a small model with synthetic weights and involves no real provider, so it is not a verification of any hosted API. Judge real proofs by the exit code plus the last line, and with exit code 1, rule out a local fault first.

Q4: Why must the commitment ID never come from the server being verified? A4: The commitment ID anchors proofs to one set of weights; if the verified party supplies it, that party can swap weights, mint a new ID, and reissue proofs, and the verification loses its anchor. Get the ID from a party you trust; files attached to the proof do not count. The stored examples are the only exception.

Q5: Can I use this to verify the API I am paying for today? A5: No. As of November 5, 2026, no mainstream provider ships FlashProve proofs in production, and the repository itself is marked not maintained. Build the verifier, internalize the exit code table, and rehearse the five-piece call, so verification is ready the day a provider ships proofs.

Related reading

This article is AI-assisted and human-edited. Last updated: 2026-11-05

FAQ

Can I run cp_verify on Windows directly?
No. The README supports x86-64 Linux only, with bash and g++ 13 or later required. The common workaround is running the steps inside a WSL2 Linux distribution; note that this is community convention rather than README text. macOS is also outside the supported list.
build.sh prints nothing for a long time. Is it stuck?
No. The README documents 1 to 2 minutes of silence, then a line starting with THE VERIFIER IS BUILT: and an exit code of 0. Lines starting with build.sh: note: are warnings, not errors. If your terminal times out, use the background build one-liner and poll tail -n 2 verifier-build.log until the exit code line appears, without starting a second build.
What does YES prove, and what does it not prove?
It proves the verifier works and that this stored proof passes the protocol check. The example uses a small model with synthetic weights and involves no real provider, so it is not a verification of any hosted API. Judge real proofs by the exit code plus the last line, and with exit code 1, rule out a local fault first.
Why must the commitment ID never come from the server being verified?
The commitment ID anchors proofs to one set of weights; if the verified party supplies it, that party can swap weights, mint a new ID, and reissue proofs, and the verification loses its anchor. Get the ID from a party you trust; files attached to the proof do not count. The stored examples are the only exception.
Can I use this to verify the API I am paying for today?
No. As of November 5, 2026, no mainstream provider ships FlashProve proofs in production, and the repository itself is marked not maintained. Build the verifier, internalize the exit code table, and rehearse the five-piece call, so verification is ready the day a provider ships proofs.

Related

Field SOP

Wire Hy4 In With Three Params: Five Steps and Three Traps

A five-step guide to wiring the final Tencent Hunyuan Hy4 API into your own workflow: create a console key and enable the model (a 402 means it is not enabled), change only base URL, API key and model (two regional endpoints, three protocol paths), keep the platform name hy4 distinct from the OpenRouter name tencent/hy4, feed images with the documented image_url and base64 pattern, then plug into CodeBuddy, Claude Code and similar clients and verify. Includes runnable Python, the 401002/402xxx/429xxx error codes, SSE mid-stream error frames, thinking mode, and three separate pricing regimes.

Nov 4, 20269 min read
Field SOP

Build Long-Running Agent Workflows with GPT-6 Astra

A hands-on SOP for building long-running agent workflows on GPT-6 Astra's real capabilities (1.05M context, 128K output, 0% alignment overreach): start with three prerequisites (OpenAI Python SDK 1.50+, the OPENAI_API_KEY environment variable, and API allowlist), then proceed in order through long-context planning, tool definition (function calling plus computer use), async invocation, mid-flight correction, and acceptance with cost control. Key points: on the first call place only the goal, acceptance criteria, tool list, and key background so the model emits a plan first; tools must specify name, description, and parameters; use streaming events plus a background queue and task-id polling for async; correct course by injecting new instructions without restart; and accept only via independent assertion scripts while keeping max_output_tokens small and setting a daily spend cap.

Sep 4, 202611 min read
Field SOP

Back up the state directory before you upgrade: OpenClaw 2.0 migration, rollback and credential-hardening SOP

For engineers already running OpenClaw: how to get up to 2.0 safely, how to roll back if it fails, and how to tighten credentials afterward. First principle — before upgrading, back up the Gateway's entire configuration and state (not a single client) and verify it is recoverable. Four upgrade steps: check → openclaw doctor --fix → restart the Gateway → verify health (model-access verification must pass for the upgrade to count). Two breaking changes: the OpenProse plugin and /prose command removed (.prose source files are preserved), and codex/* plus openai-codex/* routes move to openai/* (conflicts fixed manually). The 2026-09-01 plugin SDK deprecation (plugin-sdk-config-runtime-subpath → api.pluginConfig) is due today. Rollback is bounded: sessions created after the move to SQLite are invisible to the old version, and a full rollback also takes approvals and dedup records back. After upgrade, actively enable five things: masked credential requests, the proxy allowlist, precise authorization, role narrowing, and correcting the Incognito misconception.

Sep 1, 202614 min read