Skip to content

davidfish-g/zk-euler

Repository files navigation

ZK Verified Project Euler Solutions in Rust

Repo for storing my Project Euler Rust solutions. Each solution encrypted and accompanied by a zk proof generated by RISC Zero's zkVM, proving its correctness. I know this is complete overkill and unnecessary but I thought it was cool.

How it works

  1. Each solution runs inside RISC Zero's zkVM, a RISC-V virtual machine
  2. The zkVM produces a receipt, which is a cryptographic proof that the program executed correctly and output a specific answer
  3. The receipt is tied to an image ID, a hash of the guest program binary. This commits to the code without revealing it
  4. Anyone with the receipt and image ID can verify the proof

The proof guarantees: "There exists a program (identified by this image ID) that, given this problem number, outputs this answer." You can confirm the answer is correct by checking it against Project Euler, but you cannot determine how it was computed.

Verifying the proofs

Not all proofs might be available because they take a long time to generate, with which I'd rather not burden my silicon.

Prerequisites

Verify

# Verify a single problem
cargo run -p verify -- 1

# Verify all proofs
cargo run -p verify -- all

CLI usage

There are three binaries in this workspace:

project-euler — takes a single problem number; prints the answer and execution time.

cargo run -p project-euler --release -- <problem_number>

host — generate ZK proofs

cargo run -p host -- <problem_number|all>

verify — verify ZK proofs

cargo run -p verify -- <problem_number|all>

Adding a new problem

Create src/problems/p###.rs (zero-padded, e.g. p019.rs) with one of these signatures:

pub fn solve() -> String           // self-contained problems
pub fn solve_with_input(input: &str) -> String  // problems needing external data (put input in inputs/p###.txt)

The build script then auto-discovers new files and wires everything up. NOTE: Any change to the ELF binary, including adding new solutions, invalidates all existing proofs. I recommend just doing a few; 1,2, and 6 are quick to prove, for example.

Proof generation times

Problem Rough proof time (m3 pro)
1 <10s
2 <10s
3 ~5h
4 not generated yet (tried for 6 hours and it didn't finish)
5 not generated yet
6 <10s
7 not generated yet
8 not generated yet
9 not generated yet
10 not generated yet
11 not generated yet
12 not generated yet
13 not generated yet
14 not generated yet
15 not generated yet
16 not generated yet
17 not generated yet
18 not generated yet
19 not generated yet
20 not generated yet
21 not generated yet
22 not generated yet
23 not generated yet
27 not generated yet
34 not generated yet
35 not generated yet
50 not generated yet
67 not generated yet
92 not generated yet

Project structure

zk-euler/
├── proofs/                 # Cryptographic receipts
│   ├── image_id.json       # Hash of the guest program
│   └── p001.bin ...        # STARK proofs for each problem
├── verify/                 # Public verifier
│   └── src/main.rs
├── host/                   # Proof generator (encrypted)
│   └── src/main.rs
├── methods/                # zkVM guest build infrastructure
│   └── guest/src/main.rs   # Guest entry point (encrypted)
├── src/                    # Solution code (encrypted)
│   ├── main.rs             # CLI: cargo run -p project-euler -- <n>
│   ├── lib.rs
│   ├── utils/              # Shared utilities
│   │   ├── primes.rs
│   │   ├── digits.rs
│   │   └── math.rs
│   └── problems/           
└── inputs/                 # Problem input data files

About

Personal Project Euler Rust solution repo; private but zk-verifiable

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages