Cryptographic proof-of-inference for an SSD ResNet50 V1 FPN 640×640 object detection model. This repository contains the ONNX sub-graph, compiled GKR circuit, and proof artifacts produced by DSperse and JSTprove.
| Property | Value |
|---|---|
| Architecture | SSD ResNet50 V1 FPN 640×640 (block1 sub-graph) |
| Producer | tf2onnx (opset 13) |
| Input | [1, 64, 20, 20] float32 |
| Operators | Conv 3×3 (64→64) + Relu |
| Field | Goldilocks |
| Backend | Expander (GKR + sumcheck) |
| Prover | JSTprove via DSperse selective circuitization |
model/
├── model.onnx # block1_conv sub-graph (145 KB)
├── input.msgpack # Random input tensor [1,64,20,20]
├── slices/
│ ├── metadata.msgpack # Slice boundary metadata
│ └── slice_0/
│ ├── payload/slice_0.onnx # Conv + Relu slice (provable)
│ └── jstprove/circuit.bundle/
│ ├── circuit.bin # Compiled GKR circuit (30 MB)
│ ├── witness_solver.bin # Witness solver (39 MB)
│ └── manifest.msgpack # Circuit metadata
└── run/
├── input.msgpack # Input used for this run
├── output.msgpack # Inference outputs
├── metadata.msgpack # Run metadata
└── slice_0/
├── witness.bin # GKR witness (604 KB)
└── proof.bin # GKR proof (500 KB)
Build DSperse and JSTprove from source (Rust toolchain required):
cargo install --git https://github.com/inference-labs-inc/dsperseOr build from a local checkout:
git clone https://github.com/inference-labs-inc/dsperse.git
git clone https://github.com/inference-labs-inc/JSTprove.git
cd dsperse
cargo build --releaseDecompose the ONNX model into independently provable slices along layer boundaries. Both Conv and Relu are compiled into a single provable slice.
dsperse slice --model-dir ./model --log-level infoOutput:
shape trace complete tensors=10
determined slice points points=[0, 2]
slicing complete slices=1 tiled=0
Compile the slice into a GKR arithmetic circuit over the Goldilocks field.
dsperse compile --model-dir ./model --proof-system expander --curve goldilocks --log-level infoOutput:
compiling slices total=1
2 inputs, 151206 constraints, 16344897 vars
21 layers, 25 segments, 675484 mul + 13738570 add gates
compiled slice=0
all slices compiled count=1
This produces the circuit.bundle/ directory under slices/slice_0/jstprove/ containing the circuit binary, witness solver, and manifest.
Create a random input tensor in msgpack format:
python3 -c "
import numpy as np, msgpack
d = {'input_data': np.random.randn(1, 64, 20, 20).astype('f').flatten().tolist()}
open('model/input.msgpack', 'wb').write(msgpack.packb(d))
"Execute the full pipeline: per-slice inference via tract, witness generation, GKR proving, and verification.
dsperse full-run \
--model-dir ./model \
--input-file ./model/input.msgpack \
--proof-system expander \
--curve goldilocks \
--combined false \
--log-level infoOutput:
running inference
executing slice=slice_0 circuit=true
proving
proving circuit slices total=1
proved slice=slice_0
proving complete succeeded=1 total=1
verifying
verifying circuit slices total=1
GKR verification: true
verified slice=slice_0
verifying complete succeeded=1 total=1
full run complete
The proof cryptographically binds the inference output to the exact model weights, architecture, and input tensor. Any modification to any of these causes GKR verification: false.
To verify the proof included in this repository without re-running inference or proving:
dsperse verify --model-dir ./model --log-level info| Artifact | Size | Description |
|---|---|---|
circuit.bin |
30 MB | Compiled GKR circuit over Goldilocks encoding the Conv + Relu operations |
witness_solver.bin |
39 MB | Solver that maps inference activations to circuit witness values |
witness.bin |
604 KB | Witness: the assignment of values to all circuit wires for one inference run |
proof.bin |
500 KB | GKR proof: cryptographic attestation that the witness satisfies the circuit |
The proof can be verified by any third party with circuit.bin and proof.bin — no access to model weights or input data is required.