A small, clientless requestor that asks zkBoost to prove Ethereum execution blocks — and tracks how each request goes.
Clientless means it runs no execution or consensus client of its own. It only speaks HTTP to a Beacon API (to read blocks) and to zkBoost (to request proofs). That keeps it small and easy to run next to existing infrastructure.
proofessoor watches Ethereum blocks and drives a proof request for each one, then records how every request turns out. For each new block it reads the block from a Beacon API, builds the payload request zkBoost expects, submits it, and tracks the outcome. zkBoost coordinates the proving — it fetches the execution witness and runs whatever prover backend it's configured with.
flowchart LR
beacon[Beacon API] -->|block| proof[proofessoor]
proof -->|payload request| zk[zkBoost]
el[(execution layer)] -->|fetches witness| zk
zk -->|drives proving| backend[prover backend]
backend -->|proof| zk
zk -->|outcome| proof
proofessoor is deliberately narrow in scope: it requests proofs and tracks their status. It does not sign, run a validator, or execute blocks itself — which is what keeps it small. It also doesn't care how zkBoost proves a block: the prover backend might be a single ZisK server, a cluster, or anything else zkBoost supports. proofessoor only speaks to zkBoost's API.
cargo build --release # binary at target/release/proofessoorThe dashboard (optional, served by stream) is a separate frontend build:
cd frontend && bun install && bun run build # assets land in frontend/distPrefer containers? See Run the full stack.
Two endpoints are always required — pass them as flags or environment variables:
--beacon-url(PROOFESSOOR_BEACON_URL) — your Beacon API's HTTP endpoint. Supplies the blocks to prove. For an authenticated beacon, add--beacon-header "Name: Value"(PROOFESSOOR_BEACON_HEADER), e.g. an API key.--zkboost-url(PROOFESSOOR_ZKBOOST_URL) — your zkBoost instance's address. Coordinates the proving.
zkBoost itself needs an execution-layer RPC that serves
debug_executionWitnessByBlockHash — that's configured in zkBoost, not here.
The examples use reth-zisk as a proof type; use whatever your zkBoost is
configured for (check lists them).
proofessoor check --zkboost-url <zkboost-url> --proof-types reth-ziskLists the proof types zkBoost can currently produce, and fails if any requested type is unavailable. Run this first.
proofessoor request \
--beacon-url <beacon-url> \
--zkboost-url <zkboost-url> \
--proof-types reth-zisk \
--block-id head \
--wait --verify--block-id accepts head, genesis, finalized, justified, a slot number,
or a 0x block root. Add --wait to block until the proof finishes, --verify
to verify it through zkBoost, and --download/--out-dir to save the proof
bytes. One-shot request can take several proof types at once.
proofessoor stream \
--beacon-url <beacon-url> \
--zkboost-url <zkboost-url> \
--proof-types reth-zisk \
--state-dir ./state \
--http-addr <host:port> \
--ui-dir frontend/distFollows the Beacon API event stream and requests a proof for each new non-optimistic block. Useful flags:
--max-inflight N— cap concurrent submissions (default 1).--state-dir DIR— persist status so restarts don't re-request blocks.--http-addr HOST:PORT— serve the dashboard, metrics, and health (below).--ui-dir DIR— directory of built dashboard assets to serve.--download/--verify/--out-dir— save and/or verify completed proofs.
Stream proves one proof type at a time. It records one outcome per block, which can't represent different results for several proof types on the same block, so it accepts exactly one
--proof-typesvalue. Userequestfor multiple.
--http-addr takes a host and port of your choosing and serves three things on
that address: the dashboard at /, Prometheus metrics at /metrics, and a
health check at /health.
proofessoor status --state-dir ./statePrints each recorded request with its outcome and per-block timing (prep, zkBoost, end-to-end) — the same data the dashboard shows, from the terminal.
To run real proving on a GPU box (proofessoor + zkBoost + a prover), see
deploy/gpu/ — a Docker Compose stack, with its own README, that
wires up an ere-server (ZisK) as the backend.
cargo fmt --check
cargo clippy --all-targets --locked -- -D warnings
cargo test --locked
cargo deny check # dependency advisories + licenses
cd frontend && bun run check && bun run test && bun run buildThe toolchain is pinned in rust-toolchain.toml; lint policy lives in
Cargo.toml ([lints.clippy]) and clippy.toml; dependency policy in
deny.toml.
MIT OR Apache-2.0.
