Zero-knowledge proofs
Four layers of proof -- signatures, Merkle, Circom, RISC Zero -- each answering different questions about your agent workflows.
Treeship stacks four ZK-adjacent layers. Each one answers a different question, and each one has different performance characteristics. You pick the layers you need; Ed25519 signatures are always on.
Current status (v0.10.4). Only the first two layers ship enabled by
default. Layers 3 and 4 are behind the --features zk build flag and have
additional runtime requirements:
- Layer 1 (Ed25519 signatures): stable, always on.
- Layer 2 (Merkle audit log): stable, always on.
- Layer 3 (Circom): wired but uses an external toolchain.
treeship proveandtreeship verify-proofshell out to thecircom,node, andsnarkjsbinaries -- they must be installed on PATH. A pure-Rustark-circomproving path is scaffolded inpackages/zk-circom/src/native.rsbut the dependencies are currently commented out inpackages/zk-circom/Cargo.tomlpending ark-crate version alignment. - Layer 4 (RISC Zero): local zkVM proving via
treeship prove-chainis wired and runs end-to-end with--features zk. Bonsai hosted proving is roadmap only -- settingBONSAI_API_KEYtoday logs "Bonsai integration is coming in v0.6.0" and falls back to the local prover. - TLSNotary: not implemented. Roadmap only.
Browser-side proof verification at treeship.dev/verify does use the pure-Rust
ark-groth16 pairing math compiled to WASM with verification keys embedded at
compile time -- that part of the trust story is real today.
The four layers
Layer 1: Ed25519 signatures (always on)
Every artifact is signed the moment it's created. This is not optional and adds no measurable latency.
What it proves: this artifact was created by this Treeship and has not been modified since.
What it does not prove: anything about the artifact's contents, timing relative to other artifacts, or policy compliance.
Layer 2: Merkle audit log (instant)
Every artifact hash is appended to a local Merkle tree. The tree is append-only and tamper-evident. Generating a Merkle inclusion proof is instant because it's a tree traversal, not a computation.
What it proves: this artifact existed at this position in the log, and no artifacts before it have been removed or reordered.
What it does not prove: anything about what the artifact contains or whether it complied with policy.
Layer 3: Circom (seconds, per-artifact)
A Circom circuit takes an artifact's content and a policy, and produces a zero-knowledge proof that the artifact satisfies the policy without revealing the artifact's content.
What it proves: this artifact satisfies this policy. The verifier learns the policy was met but does not learn the artifact's contents.
What it does not prove: anything about the sequence of artifacts or the overall session integrity.
Performance: proof generation typically takes 1-5 seconds depending on circuit complexity and on how fast the local snarkjs shell-out completes. CLI verification (also via snarkjs) is roughly in the same range; browser-side Groth16 pairing verification via the embedded ark-groth16 WASM is under 100ms.
Requirements today: the CLI must be built with --features zk, and the
circom, node, and snarkjs binaries must be installed on PATH. If they
are not, treeship prove and treeship verify-proof will fail at the
shell-out step. Run treeship zk-setup to see what is detected on your
system.
Layer 4: RISC Zero (minutes, per-session, background)
A RISC Zero proof covers an entire session: a sequence of artifacts, their Merkle positions, and the session's causal chain. This is the most expensive layer and is intended to run in the background.
What it proves: the session chain is intact and every artifact's Ed25519 signature verifies against the same public key, all checked inside the zkVM. The verifier learns the chain is well-formed without re-running every per-artifact check itself.
What it does not prove today: the per-artifact Circom policy proofs are not currently re-verified inside the RISC Zero guest. Composing the two layers end-to-end is roadmap work, not a property of the v0.10.4 receipt.
What it does not prove at all: anything about network interactions or external API responses (that's TLSNotary's job, and TLSNotary is not yet implemented in this repo).
Performance: local CPU proving takes several minutes per session and is expected to run in the background -- the daemon kicks off chain proofs asynchronously. Verification of a finished receipt is well under a second. Bonsai hosted proving would be faster but is not wired yet (see status callout at the top of this page).
Requirements today: --features zk build flag. The RISC Zero zkVM links
in via treeship-zk-risc0. The image ID is embedded at compile time, so
verification is fully offline once a receipt exists.
How layers compose
Each layer builds on the ones below it. A fully-proved session looks like this:
{
"artifact": {
"content_hash": "sha256:abc123...",
"ed25519_signature": "sig:...",
"merkle_proof": {
"root": "0xdef...",
"path": ["0x1a...", "0x2b...", "0x3c..."],
"index": 42
},
"circom_proof": {
"policy": "budget_under_10k",
"proof": "base64:...",
"public_signals": ["1"]
}
},
"session_proof": {
"risc_zero_receipt": "base64:...",
"session_id": "session:...",
"artifact_count": 47
}
}You don't need all layers for every use case. A simple audit trail needs only layers 1 and 2. Policy compliance adds layer 3. Full session integrity adds layer 4.
Verification commands
Verify an artifact's signature (always available):
treeship verify artifact.jsonVerify a Merkle inclusion proof (always available):
treeship verify --merkle artifact.jsonVerify a Circom policy proof (requires --features zk build and snarkjs
installed on PATH):
treeship verify-proof art_xxx.policy-checker.zkproofGenerate a Circom proof for a single artifact (same build requirements as
above, plus circom and node on PATH):
treeship prove --circuit policy-checker --artifact art_xxx --policy ./policy.jsonProve a full session chain via RISC Zero (requires --features zk, runs for
several minutes on CPU):
treeship prove-chain <session_id>TLSNotary (roadmap)
TLSNotary would prove that a specific HTTPS request and response occurred between an agent and an external API. This is intended for commerce workflows where you need to prove that a payment API returned a specific confirmation, or that a price quote was real.
TLSNotary is not yet implemented in Treeship. There is no notary integration in packages/ today; the section here describes the intended shape, not shipping code.
TLSNotary is scoped to commerce workflows and is roadmap only. Most agent attestation use cases do not need it.
Status
| Layer | Status | Notes |
|---|---|---|
| Ed25519 signatures | Stable, always on | Since v0.1.0 |
| Merkle audit log | Stable, always on | Since v0.2.0 |
| Circom proofs | Wired, external toolchain required | --features zk build, plus circom + node + snarkjs on PATH. Pure-Rust ark-circom proving path is scaffolded but the dependencies are commented out in packages/zk-circom/Cargo.toml. |
| RISC Zero chain proofs (local) | Wired | --features zk build. Local CPU proving via risc0-zkvm::default_prover(). Several minutes per chain. |
| RISC Zero Bonsai (hosted) | Roadmap | BONSAI_API_KEY is detected but unused; logs "coming in v0.6.0" and falls back to the local prover. |
| TLSNotary | Roadmap | Not implemented in this repo. |
Build flag
ZK layers (Circom and RISC Zero) are behind a feature flag to keep the default binary small. To build with ZK support:
cargo build --features zkThe Ed25519 and Merkle layers are always included.
Trust model
Every ZK layer in Treeship is designed to work locally without contacting a Treeship-operated service to produce or verify a proof.
Fully local, no external trust:
- Ed25519 signatures -- your key, your machine.
- Merkle proofs -- your key, your machine, self-contained proof file.
- Circom proving (today) -- runs on your CPU via a local
snarkjs+nodecircomshell-out. The witness, proof, and verification keys never leave your machine, but the toolchain dependency is real and is your responsibility to install. A pure-Rustark-circompath is scaffolded inpackages/zk-circom/src/native.rs; once the ark-crate version alignment is resolved (# native = [...]inpackages/zk-circom/Cargo.toml) the Node.js dependency goes away.
- Circom verification in the CLI -- shells out to local
snarkjs. Same Node.js dependency as proving. - Circom verification in the browser (
treeship.dev/verify) -- pure Rust viaark-groth16compiled to WASM, with verification keys embedded at compile time inpackages/core-wasm/src/zk.rs. No network call. Hub cannot forge a passing result. - RISC Zero chain proving and verification -- local zkVM via the
risc0-zkvmcrate. The image ID is embedded at compile time, so a finished receipt can be verified offline.
One-time trust assumption (acceptable):
- Groth16 trusted setup uses the Hermez powers-of-tau ceremony (thousands of
participants). Maintainers ran the per-circuit phase 2 once and the finished
*.zkey/*_vk.jsonfiles are committed underpackages/zk-circom/zkeys/. Users never run the ceremony.
Roadmap (not opt-in today):
- RISC Zero Bonsai would be a hosted prover for chain proofs. Setting
BONSAI_API_KEYis detected by the prover but is not yet wired -- the code logs "Bonsai integration is coming in v0.6.0" and runs the local prover instead. Track this as roadmap, not as an available opt-in.
Verify offline with no server trust (requires --features zk build and
snarkjs on PATH):
treeship verify-proof art_xxx.policy-checker.zkproofThis works air-gapped today via the local snarkjs verifier. The browser
verifier at treeship.dev/verify runs the equivalent Groth16 pairing check
in pure Rust WASM with no shell-out and no network call -- Hub cannot forge a
passing result. Once the in-repo ark-circom path lands, the CLI will offer
the same pure-Rust verification with no toolchain dependency.