├── .dockerignore ├── .github ├── actions │ └── setup │ │ └── action.yml ├── runs-on.yml └── workflows │ └── suite.yml ├── .gitignore ├── .vscode └── settings.json ├── Cargo.lock ├── Cargo.toml ├── Dockerfile ├── README.md ├── append.py ├── eval.sh ├── eval ├── Cargo.toml ├── blocks │ ├── 17106222.bin │ ├── 18635849.bin │ ├── 19409717.bin │ ├── 19409768.bin │ ├── 19422264.bin │ ├── 19425663.bin │ ├── 19425776.bin │ ├── 19426396.bin │ ├── 19426535.bin │ └── 19426587.bin ├── build.rs └── src │ ├── main.rs │ ├── risc0.rs │ ├── sp1.rs │ ├── types.rs │ └── utils.rs ├── fixtures ├── 20526626.bin ├── 20526627.bin ├── 20526628.bin ├── 20526629.bin ├── 20526630.bin ├── 20528708.bin ├── 20528709.bin ├── 20528710.bin ├── 20528711.bin ├── 20528712.bin ├── helios │ └── proof_inputs.cbor ├── risc0 │ ├── proof.json │ ├── public.json │ └── verification_key.json └── zk-email │ └── email.json ├── install-1.82-toolchain.sh ├── install.sh ├── programs ├── ecdsa-verify-risc0 │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── ecdsa-verify-sp1 │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── eddsa-verify-risc0 │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── eddsa-verify-sp1 │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── fibonacci │ ├── Cargo.lock │ ├── Cargo.toml │ ├── elf │ │ └── riscv32im-succinct-zkvm-elf │ └── src │ │ └── main.rs ├── groth-risc0 │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── groth-sp1 │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── helios-risc0 │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── helios-sp1 │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── keccak256-risc0 │ ├── Cargo.lock │ ├── Cargo.toml │ ├── elf │ │ └── riscv32im-succinct-zkvm-elf │ └── src │ │ └── main.rs ├── keccak256-sp1 │ ├── Cargo.lock │ ├── Cargo.toml │ ├── elf │ │ └── riscv32im-succinct-zkvm-elf │ └── src │ │ └── main.rs ├── loop │ ├── Cargo.lock │ ├── Cargo.toml │ ├── elf │ │ └── riscv32im-succinct-zkvm-elf │ └── src │ │ └── main.rs ├── rsp-risc0 │ ├── Cargo.lock │ ├── Cargo.toml │ ├── elf │ │ └── riscv32im-succinct-zkvm-elf │ └── src │ │ └── main.rs ├── rsp-sp1 │ ├── Cargo.lock │ ├── Cargo.toml │ ├── elf │ │ └── riscv32im-succinct-zkvm-elf │ └── src │ │ └── main.rs ├── sha256-risc0 │ ├── Cargo.lock │ ├── Cargo.toml │ ├── elf │ │ └── riscv32im-succinct-zkvm-elf │ └── src │ │ └── main.rs ├── sha256-sp1 │ ├── Cargo.lock │ ├── Cargo.toml │ ├── elf │ │ └── riscv32im-succinct-zkvm-elf │ └── src │ │ └── main.rs ├── ssz-withdrawals │ ├── Cargo.lock │ ├── Cargo.toml │ ├── elf │ │ └── riscv32im-succinct-zkvm-elf │ └── src │ │ ├── beacon │ │ ├── hints.rs │ │ ├── mod.rs │ │ ├── prove.rs │ │ ├── types.rs │ │ └── utils.rs │ │ ├── main.rs │ │ └── proof.rs ├── tendermint-risc0 │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ │ ├── fixtures │ │ ├── 1 │ │ │ ├── next_validators.json │ │ │ ├── signed_header.json │ │ │ └── validators.json │ │ ├── 2 │ │ │ ├── next_validators.json │ │ │ ├── signed_header.json │ │ │ └── validators.json │ │ ├── small-1 │ │ │ ├── next_validators.json │ │ │ ├── signed_header.json │ │ │ └── validators.json │ │ └── small-2 │ │ │ ├── next_validators.json │ │ │ ├── signed_header.json │ │ │ └── validators.json │ │ └── main.rs ├── tendermint-sp1 │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ │ ├── fixtures │ │ ├── 1 │ │ │ ├── next_validators.json │ │ │ ├── signed_header.json │ │ │ └── validators.json │ │ ├── 2 │ │ │ ├── next_validators.json │ │ │ ├── signed_header.json │ │ │ └── validators.json │ │ ├── small-1 │ │ │ ├── next_validators.json │ │ │ ├── signed_header.json │ │ │ └── validators.json │ │ └── small-2 │ │ │ ├── next_validators.json │ │ │ ├── signed_header.json │ │ │ └── validators.json │ │ └── main.rs ├── zk-email-risc0 │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ │ └── main.rs └── zk-email-sp1 │ ├── Cargo.lock │ ├── Cargo.toml │ └── src │ └── main.rs ├── rustfmt.toml ├── sweep.py ├── workflow_cpu.sh └── workflow_gpu.sh /.dockerignore: -------------------------------------------------------------------------------- 1 | target/* -------------------------------------------------------------------------------- /.github/actions/setup/action.yml: -------------------------------------------------------------------------------- 1 | name: Test setup 2 | inputs: 3 | pull_token: 4 | description: "Token to use for private repo access" 5 | required: true 6 | setup_gcc: 7 | description: "Whether to setup GCC or not" 8 | required: false 9 | default: 'true' 10 | setup_aws_cli: 11 | description: "Whether to install AWS CLI or not" 12 | required: false 13 | default: 'true' 14 | runs: 15 | using: "composite" 16 | steps: 17 | - name: Set up git private repo access 18 | shell: bash 19 | run: | 20 | git config --global url."https://${{ inputs.pull_token }}@github.com/".insteadOf ssh://git@github.com 21 | git config --global url."https://${{ inputs.pull_token }}@github.com".insteadOf https://github.com 22 | 23 | - name: Install Go 1.22 24 | uses: actions/setup-go@v5 25 | with: 26 | go-version: "1.22" 27 | cache-dependency-path: "**/go.sum" 28 | 29 | - name: Print go version 30 | shell: bash 31 | run: go version 32 | 33 | - name: Check GCC version 34 | id: check-gcc 35 | shell: bash 36 | run: | 37 | if command -v gcc &> /dev/null; then 38 | echo "gcc_exists=true" >> $GITHUB_OUTPUT 39 | echo "gcc_version=$(gcc --version | head -n1 | awk '{print $NF}')" >> $GITHUB_OUTPUT 40 | else 41 | echo "gcc_exists=false" >> $GITHUB_OUTPUT 42 | fi 43 | 44 | - name: Setup GCC 45 | uses: Dup4/actions-setup-gcc@v1 46 | if: inputs.setup_gcc == 'true' && steps.check-gcc.outputs.gcc_exists != 'true' 47 | with: 48 | version: latest 49 | 50 | - uses: actions/setup-python@v5 51 | with: 52 | python-version: '3.10' 53 | 54 | - name: Install AWS CLI v2 55 | if: inputs.setup_aws_cli == 'true' 56 | shell: bash 57 | run: | 58 | if ! command -v aws &> /dev/null; then 59 | echo "AWS CLI not found. Installing..." 60 | python3 -m pip install --user awscli 61 | echo "$HOME/.local/bin" >> $GITHUB_PATH 62 | else 63 | echo "AWS CLI is already installed." 64 | fi 65 | export PATH="$HOME/.local/bin:$PATH" 66 | aws --version 67 | 68 | - name: rust-cache 69 | uses: actions/cache@v3 70 | with: 71 | path: | 72 | ~/.cargo/bin/ 73 | ~/.cargo/registry/index/ 74 | ~/.cargo/registry/cache/ 75 | ~/.cargo/git/db/ 76 | target/ 77 | ~/.rustup/ 78 | ~/.sp1/circuits/plonk/ 79 | ~/.sp1/circuits/groth16/ 80 | key: rust-1.84.0-${{ hashFiles('**/Cargo.toml') }} 81 | restore-keys: rust-1.84.0- 82 | 83 | - name: Setup toolchain 84 | id: rustc-toolchain 85 | shell: bash 86 | run: | 87 | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- --default-toolchain 1.84.0 -y 88 | . "$HOME/.cargo/env" 89 | echo "$HOME/.cargo/bin" >> $GITHUB_PATH 90 | 91 | # install pkg-config and openssl 92 | - name: Install pkg-config and openssl 93 | shell: bash 94 | run: | 95 | if ! dpkg -s pkg-config libssl-dev &> /dev/null; then 96 | echo "pkg-config and/or libssl-dev not found. Installing..." 97 | sudo apt-get update 98 | sudo apt-get install -y pkg-config libssl-dev 99 | else 100 | echo "pkg-config and libssl-dev are already installed." 101 | fi 102 | 103 | - name: Set up Docker 104 | uses: docker/setup-buildx-action@v3 105 | with: 106 | driver-opts: | 107 | image=public.ecr.aws/vend/moby/buildkit:buildx-stable-1 -------------------------------------------------------------------------------- /.github/runs-on.yml: -------------------------------------------------------------------------------- 1 | images: 2 | nvidia-linux: 3 | platform: "linux" 4 | arch: "x64" 5 | ami: "ami-0a63dc9cb9e934ba3" 6 | owner: "421253708207" 7 | 8 | dlami-x64: 9 | platform: "linux" 10 | arch: "x64" 11 | owner: "898082745236" 12 | name: "Deep Learning Base OSS Nvidia Driver GPU AMI (Ubuntu 22.04)*" 13 | 14 | runners: 15 | aws-m7i-xlarge: 16 | family: ["m7i.xlarge"] 17 | image: ubuntu22-full-x64 18 | aws-m7i-2xlarge: 19 | family: ["m7i.2xlarge"] 20 | image: ubuntu22-full-x64 21 | aws-m7i-4xlarge: 22 | family: ["m7i.4xlarge"] 23 | image: ubuntu22-full-x64 24 | aws-m7i-8xlarge: 25 | family: ["m7i.8xlarge"] 26 | image: ubuntu22-full-x64 27 | aws-m7i-16xlarge: 28 | family: ["m7i.16xlarge"] 29 | image: ubuntu22-full-x64 30 | aws-m7i-24xlarge: 31 | family: ["m7i.24xlarge"] 32 | image: ubuntu22-full-x64 33 | aws-g6-xlarge: 34 | family: ["g6.xlarge"] 35 | image: dlami-x64 36 | aws-g6-2xlarge: 37 | family: ["g6.2xlarge"] 38 | image: dlami-x64 39 | aws-g6-4xlarge: 40 | family: ["g6.4xlarge"] 41 | image: dlami-x64 42 | aws-g6-8xlarge: 43 | family: ["g6.8xlarge"] 44 | image: dlami-x64 45 | aws-g6-12xlarge: 46 | family: ["g6.12xlarge"] 47 | image: dlami-x64 48 | aws-g6-16xlarge: 49 | family: ["g6.16xlarge"] 50 | image: dlami-x64 -------------------------------------------------------------------------------- /.github/workflows/suite.yml: -------------------------------------------------------------------------------- 1 | name: Benchmark Suite 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | instances: 7 | required: true 8 | type: string 9 | provers: 10 | required: true 11 | type: string 12 | programs: 13 | required: true 14 | type: string 15 | shard_sizes: 16 | required: true 17 | type: string 18 | 19 | jobs: 20 | run: 21 | timeout-minutes: 1440 22 | strategy: 23 | fail-fast: false 24 | matrix: 25 | prover: ${{ fromJSON(github.event.inputs.provers) }} 26 | instance: ${{ fromJSON(github.event.inputs.instances) }} 27 | shard_size: ${{ fromJSON(github.event.inputs.shard_sizes) }} 28 | program: ${{ fromJSON(github.event.inputs.programs) }} 29 | name: Run (${{matrix.prover}}, ${{matrix.program}}, ${{ matrix.instance }}, ${{ matrix.shard_size }}) 30 | runs-on: 31 | [ 32 | "runs-on", 33 | "runner=${{ matrix.instance }}", 34 | "spot=false", 35 | "run-id=${{ github.run_id }}", 36 | ] 37 | steps: 38 | - name: Checkout sources 39 | uses: actions/checkout@v4 40 | 41 | - name: Configure Cargo for private repositories 42 | run: | 43 | git config --global url."https://${{ secrets.PRIVATE_PULL_TOKEN }}@github.com/".insteadOf "https://github.com/" 44 | mkdir -p ~/.cargo 45 | echo "[net]" >> ~/.cargo/config.toml 46 | echo 'git-fetch-with-cli = true' >> ~/.cargo/config.toml 47 | 48 | - name: Setup workflow 49 | uses: ./.github/actions/setup 50 | 51 | - name: Install dependencies 52 | run: | 53 | sudo apt-get update 54 | DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC sudo apt-get install -y \ 55 | curl \ 56 | build-essential \ 57 | protobuf-compiler \ 58 | git \ 59 | libssl-dev \ 60 | pkg-config \ 61 | build-essential \ 62 | libc6 \ 63 | gcc \ 64 | g++ \ 65 | clang 66 | 67 | - name: Check CUDA installation 68 | if: ${{ contains(matrix.instance, 'g6') }} 69 | run: | 70 | echo "Checking CUDA paths..." 71 | ls -l /usr/local/cuda* || true 72 | echo "CUDA_HOME=$CUDA_HOME" 73 | echo "PATH=$PATH" 74 | which nvcc || true 75 | 76 | - name: Setup CUDA paths 77 | if: ${{ contains(matrix.instance, 'g6') }} 78 | run: | 79 | echo "/usr/local/cuda-12.4/bin" >> $GITHUB_PATH 80 | echo "LD_LIBRARY_PATH=/usr/local/cuda-12.4/lib64:${LD_LIBRARY_PATH}" >> $GITHUB_ENV 81 | echo "CUDA_HOME=/usr/local/cuda-12.4" >> $GITHUB_ENV 82 | 83 | - name: Run nvidia-smi 84 | if: ${{ contains(matrix.instance, 'g6') }} 85 | run: | 86 | nvidia-smi 87 | 88 | - name: Check nvcc version 89 | if: ${{ contains(matrix.instance, 'g6') }} 90 | run: | 91 | nvcc --version 92 | 93 | - name: Run install.sh 94 | run: | 95 | bash install.sh 96 | 97 | - name: Make benchmarks directory 98 | run: mkdir -p ${{ github.workspace }}/benchmarks 99 | 100 | - name: Run benchmark 101 | run: | 102 | python3 sweep.py \ 103 | --filename benchmark \ 104 | --trials 1 \ 105 | --programs ${{ matrix.program }} \ 106 | --provers ${{ matrix.prover }} \ 107 | --shard-sizes ${{ matrix.shard_size }} 108 | 109 | - name: List benchmark results 110 | run: ls -la ${{ github.workspace }}/benchmarks 111 | 112 | - name: Echo benchmark results 113 | run: cat benchmarks/benchmarks_latest.csv 114 | 115 | - name: Append the benchmark results to the google sheet with a lock 116 | working-directory: ${{ github.workspace }} 117 | run: | 118 | python3 -m pip install gspread redis python-redis-lock google-auth 119 | python3 append.py 120 | env: 121 | REDIS_HOST: ${{ secrets.REDIS_HOST }} 122 | REDIS_PASSWORD: ${{ secrets.REDIS_PASSWORD }} 123 | GSHEET_CLIENT_EMAIL: ${{ secrets.GSHEET_CLIENT_EMAIL }} 124 | GSHEET_PRIVATE_KEY: ${{ secrets.GSHEET_PRIVATE_KEY }} 125 | GITHUB_RUN_ID: ${{ github.run_id }} 126 | GITHUB_SHA: ${{ github.sha }} 127 | GITHUB_MATRIX_INSTANCE: ${{ matrix.instance }} 128 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Cargo build 2 | **/target 3 | 4 | # Cargo config 5 | .cargo 6 | 7 | # Profile-guided optimization 8 | /tmp 9 | pgo-data.profdata 10 | 11 | # MacOS nuisances 12 | .DS_Store 13 | 14 | # Github commit file 15 | COMMIT_HASH 16 | 17 | # Benchmark results 18 | **/.csv 19 | **/*.csv 20 | 21 | # NVIDIA profiling files 22 | *.nsys-rep 23 | *.sqlite -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "rust-analyzer.procMacro.enable": true, 3 | "rust-analyzer.cargo.features": ["risc0", "sp1", "cuda"], 4 | "rust-analyzer.check.features": ["risc0", "sp1", "cuda"] 5 | } 6 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = ["eval"] 3 | 4 | resolver = "2" 5 | 6 | [profile.dev] 7 | opt-level = 3 8 | 9 | [profile.dev.build-override] 10 | opt-level = 3 11 | 12 | [profile.release] 13 | opt-level = 3 14 | lto = true 15 | 16 | [profile.fast] 17 | inherits = "release" 18 | debug = true 19 | debug-assertions = true 20 | 21 | [profile.release.build-override] 22 | opt-level = 3 23 | 24 | [patch.crates-io] 25 | ark-ff = { git = "https://github.com/a16z/arkworks-algebra", branch = "optimize/field-from-u64" } 26 | ark-ec = { git = "https://github.com/a16z/arkworks-algebra", branch = "optimize/field-from-u64" } 27 | ark-serialize = { git = "https://github.com/a16z/arkworks-algebra", branch = "optimize/field-from-u64" } 28 | revm-interpreter = { git = "https://github.com/sp1-patches/revm-new", branch = "john/update-for-v1" } 29 | revm-primitives = { git = "https://github.com/sp1-patches/revm-new", branch = "john/update-for-v1" } 30 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nvidia/cuda:12.5.1-devel-ubuntu20.04 2 | 3 | # Install system dependencies 4 | RUN apt-get update && DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get install -y \ 5 | curl \ 6 | build-essential \ 7 | protobuf-compiler \ 8 | git \ 9 | libssl-dev \ 10 | pkg-config \ 11 | python3 \ 12 | python3-pip \ 13 | build-essential \ 14 | libc6 \ 15 | gcc \ 16 | g++ \ 17 | docker.io \ 18 | && rm -rf /var/lib/apt/lists/* 19 | 20 | # Install Rust separately for better caching 21 | RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y 22 | ENV PATH="/root/.cargo/bin:${PATH}" 23 | ENV PS1="\u@\h:\w \$ " 24 | 25 | # Copy just the install script first 26 | COPY install.sh /install.sh 27 | RUN chmod +x /install.sh && /install.sh 28 | 29 | # Set the working directory 30 | WORKDIR /usr/src/app 31 | 32 | # Copy source code last since it changes most frequently 33 | COPY . /usr/src/app 34 | 35 | ENTRYPOINT ["/bin/bash", "-c"] -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ZKVM-Perf And You 🫵🏻 2 | 3 | Welcome to ZKVM-Perf, a powerful benchmarking tool for ZKVM implementations. This guide covers both automated workflow-based benchmarking and manual benchmarking processes. 4 | 5 | ## Automated Benchmarking 6 | 7 | ### Quick Start Guide 8 | 9 | 1. Go to the [Actions tab](https://github.com/succinctlabs/zkvm-perf/actions) in the ZKVM-Perf repository. 10 | 2. Click on the "Execute ZKVM-Perf (Matrix)" workflow. 11 | 3. Click the "Run workflow" button. 12 | 4. (Optional) Customize parameters or use defaults. 13 | 5. Click the green "Run workflow" button at the bottom. 14 | 6. Wait for all matrix jobs to complete. 15 | 7. Check individual job results and download CSV artifacts for detailed analysis. 16 | 17 | ### Workflow Details 18 | 19 | The benchmarking process is split into two main workflows: 20 | 21 | 1. `adhoc-matrix.yml`: Orchestrates the overall benchmarking process. 22 | 2. `run-on-runner.yml`: Executes the actual benchmarks on EC2 instances. 23 | 24 | #### adhoc-matrix.yml 25 | 26 | This workflow sets up the benchmarking environment and triggers individual benchmark runs. 27 | 28 | ##### Inputs 29 | 30 | - `provers`: Provers to use (comma-separated, default: 'sp1') 31 | - `programs`: Programs to benchmark (comma-separated, default: 'loop10k, loop100k, loop1m, loop3m, loop10m, loop30m, loop100m, fibonacci,tendermint,reth1,reth2') 32 | - `filename`: Filename for the benchmark (default: 'benchmark') 33 | - `trials`: Number of trials to run (default: '1') 34 | - `sp1_ref`: SP1 reference (commit hash or branch name, default: 'dev') 35 | - `additional_params`: Additional parameters as JSON (default: '{"hashfns":"poseidon","shard_sizes":"22"}') 36 | 37 | ##### Matrix Strategy 38 | 39 | The workflow runs benchmarks on two types of EC2 instances: 40 | 41 | - GPU: g6.16xlarge 42 | - CPU: r7i.16xlarge 43 | 44 | #### run-on-runner.yml 45 | 46 | This workflow is triggered by `adhoc-matrix.yml` and runs the actual benchmarks on the specified EC2 instance. 47 | 48 | ##### Key Steps 49 | 50 | 1. Sets up the Docker environment. 51 | 2. Builds the Docker image with the specified SP1 reference. 52 | 3. Runs the benchmark using the `sweep.py` script. 53 | 4. Uploads the benchmark results as artifacts. 54 | 55 | ### Running Automated Benchmarks 56 | 57 | 1. **Navigate to the Actions Tab** 58 | Go to the [Actions tab](https://github.com/succinctlabs/zkvm-perf/actions) in the repository. 59 | 60 | 2. **Select the Workflow** 61 | Click on "Execute ZKVM-Perf (Matrix)". 62 | 63 | 3. **Configure the Run** 64 | 65 | - You can use the default settings for a quick start. 66 | - Customize inputs as needed. 67 | 68 | 4. **Start the Benchmark** 69 | Click "Run workflow". 70 | 71 | 5. **Monitor Progress** 72 | 73 | - The workflow will start two jobs: one for GPU and one for CPU. 74 | - Each job will trigger a separate `run-on-runner` workflow. 75 | 76 | 6. **Access Results** 77 | - Once complete, each job will upload its results as an artifact. 78 | - Download the artifacts to analyze the benchmark data. 79 | - A combined results file will also be available. 80 | 81 | ## Manual Benchmarking 82 | 83 | ### Setup 84 | 85 | 1. Install Rust: 86 | 87 | ```sh 88 | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh 89 | rustup install nightly 90 | ``` 91 | 92 | 2. Install the [SP1 toolchain](https://docs.succinct.xyz/getting-started/install.html): 93 | 94 | ```sh 95 | curl -L https://sp1.succinct.xyz | bash 96 | source ~/.bashrc 97 | sp1up 98 | cargo prove --version 99 | ``` 100 | 101 | 3. Install the [Risc0 toolchain](https://dev.risczero.com/api/zkvm/install): 102 | 103 | ```sh 104 | curl -L https://risczero.com/install | bash 105 | source ~/.bashrc 106 | rzup install 107 | cargo risczero --version 108 | ``` 109 | 110 | 4. Install [Docker](https://docs.docker.com/engine/install/ubuntu/). 111 | 112 | 5. If using NVIDIA GPUs, install the [NVIDIA Container Toolkit](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html). 113 | 114 | **Note:** Run one round of a small program (e.g., Fibonacci) to download the R0 docker image before benchmarking to avoid affecting benchmark times. 115 | 116 | **Note:** On Ubuntu 22.04, you might need to install libssl1.0 for the Risc0 toolchain. Follow these [instructions](https://stackoverflow.com/questions/72133316/libssl-so-1-1-cannot-open-shared-object-file-no-such-file-or-directory/73604364#73604364). 117 | 118 | ### Running a Manual Sweep 119 | 120 | To conduct a sweep of the benchmarks: 121 | 122 | ```sh 123 | python3 sweep.py [options] 124 | ``` 125 | 126 | Available options: 127 | 128 | - `--filename`: Filename for the benchmark (default: "benchmark") 129 | - `--trials`: Number of trials to run (default: 1) 130 | - `--programs`: List of programs to benchmark (choices: loop10k, loop100k, loop1m, loop3m, loop10m, loop30m, loop100m, fibonacci, tendermint, reth1, reth2) 131 | - `--provers`: List of provers to use (choices: sp1, risc0) 132 | - `--hashfns`: List of hash functions to use (currently only poseidon is supported) 133 | - `--shard-sizes`: List of shard sizes to use 134 | - `--block-1`: Block number for reth1 (default: "17106222") 135 | - `--block-2`: Block number for reth2 (default: "19409768") 136 | 137 | ### Running a Single Benchmark 138 | 139 | To run a single benchmark: 140 | 141 | ```sh 142 | ./eval.sh [block_number] 143 | ``` 144 | 145 | Examples: 146 | 147 | ``` 148 | ./eval.sh fibonacci sp1 poseidon 22 benchmark 149 | ./eval.sh fibonacci jolt-zkvm poseidon 22 benchmark 150 | ./eval.sh fibonacci risc0 poseidon 22 benchmark 151 | ./eval.sh reth sp1 poseidon 22 benchmark 19409768 152 | ``` 153 | 154 | ## Analyzing Results 155 | 156 | - Each benchmark run produces a CSV file with detailed performance metrics. 157 | - The CSV includes the instance type, allowing for easy comparison between GPU and CPU performance. 158 | - Use the combined results file for a comprehensive view of all benchmarks. 159 | 160 | ## Troubleshooting 161 | 162 | If you encounter issues: 163 | 164 | 1. Check the logs of both the matrix job and the individual runner jobs. 165 | 2. Ensure your AWS credentials and permissions are correctly set up. 166 | 3. Verify that the SP1 reference is valid and accessible. 167 | 4. For GPU jobs, confirm that GPU support is properly configured in the EC2 instance. 168 | 169 | ### Common Issues 170 | 171 | For C++ compiler and library issues: 172 | 173 | Ubuntu/Debian: 174 | 175 | ```sh 176 | sudo apt update && sudo apt upgrade 177 | sudo apt install build-essential libc6 178 | ``` 179 | 180 | CentOS/RHEL: 181 | 182 | ``` 183 | sudo yum update 184 | sudo yum groupinstall "Development Tools" 185 | sudo yum install -y gcc-c++ 186 | ``` 187 | 188 | Fedora: 189 | 190 | ```sh 191 | sudo dnf update 192 | sudo dnf groupinstall "Development Tools" 193 | ``` 194 | 195 | Setting up NVIDIA: 196 | 197 | ```sh 198 | sudo nvidia-ctk runtime configure --runtime=docker 199 | sudo systemctl restart docker 200 | ``` 201 | 202 | ## Contributing 203 | 204 | We welcome contributions to improve ZKVM-Perf! If you encounter issues or have suggestions: 205 | 206 | 1. Check existing issues in the repository. 207 | 2. If your issue is new, create a detailed bug report or feature request. 208 | 3. For code contributions, please submit a pull request with a clear description of your changes. 209 | 210 | Happy benchmarking! 🚀 211 | -------------------------------------------------------------------------------- /append.py: -------------------------------------------------------------------------------- 1 | import gspread 2 | import os 3 | import json 4 | import redis 5 | import redis_lock 6 | import csv, json, sys 7 | from google.oauth2.service_account import Credentials 8 | 9 | REDIS_HOST = os.getenv("REDIS_HOST") 10 | REDIS_PASSWORD = os.getenv("REDIS_PASSWORD") 11 | GSHEET_CLIENT_EMAIL = os.getenv("GSHEET_CLIENT_EMAIL") 12 | GSHEET_PRIVATE_KEY = os.getenv("GSHEET_PRIVATE_KEY") 13 | GITHUB_RUN_ID = os.getenv("GITHUB_RUN_ID") 14 | GITHUB_SHA = os.getenv("GITHUB_SHA") 15 | GITHUB_MATRIX_INSTANCE = os.getenv("GITHUB_MATRIX_INSTANCE") 16 | 17 | rc = redis.Redis( 18 | host=REDIS_HOST, 19 | port=6379, 20 | password=REDIS_PASSWORD, 21 | ssl=True 22 | ) 23 | 24 | with redis_lock.Lock(rc, "zkvm-perf-wip-gh-action", expire=60): 25 | gc = gspread.service_account_from_dict({ 26 | "type": "service_account", 27 | "project_id": "succinct-benchmarking", 28 | "client_email": GSHEET_CLIENT_EMAIL, 29 | "private_key": GSHEET_PRIVATE_KEY.replace("\\n", "\n"), 30 | "token_uri": "https://oauth2.googleapis.com/token", 31 | }) 32 | 33 | sheet = gc.open("SP1 Datasheets") 34 | worksheet = sheet.worksheet("Runs") 35 | 36 | with open("./benchmarks/benchmarks_latest.csv") as f: 37 | reader = csv.reader(f) 38 | next(reader) 39 | data = list(reader) 40 | for row in data: 41 | row.insert(0, GITHUB_MATRIX_INSTANCE) 42 | row.insert(0, GITHUB_SHA) 43 | row.insert(0, GITHUB_RUN_ID) 44 | worksheet.append_row(row) 45 | -------------------------------------------------------------------------------- /eval.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | echo "Running $1, $2, $3, $4, $5" 4 | 5 | # Get program directory name as $1 and append "-$2" to it if $1 == "tendermint" 6 | if [ "$1" = "tendermint" ] || [ "$1" = "reth" ]; then 7 | program_directory="${1}-$2" 8 | else 9 | program_directory="$1" 10 | fi 11 | # If program_directory starts with loop, then set it to loop 12 | if [[ $program_directory == loop* ]]; then 13 | program_directory="loop" 14 | fi 15 | if [[ $program_directory == fibonacci* ]]; then 16 | program_directory="fibonacci" 17 | fi 18 | if [[ $program_directory == sha256* ]]; then 19 | program_directory="sha256-$2" 20 | fi 21 | if [[ $program_directory == keccak256* ]]; then 22 | program_directory="keccak256-$2" 23 | fi 24 | if [[ $program_directory == rsp* ]]; then 25 | program_directory="rsp-$2" 26 | fi 27 | if [[ $program_directory == eddsa-verify* ]]; then 28 | program_directory="eddsa-verify-$2" 29 | fi 30 | if [[ $program_directory == ecdsa-verify* ]]; then 31 | program_directory="ecdsa-verify-$2" 32 | fi 33 | if [[ $program_directory == helios* ]]; then 34 | program_directory="helios-$2" 35 | fi 36 | if [[ $program_directory == groth16-proof-verify* ]]; then 37 | program_directory="groth-$2" 38 | fi 39 | if [[ $program_directory == zk-email* ]]; then 40 | program_directory="zk-email-$2" 41 | fi 42 | 43 | echo "Building program" 44 | 45 | # cd to program directory computed above 46 | cd "programs/$program_directory" 47 | 48 | # If the prover is sp1, then build the program. 49 | if [ "$2" == "sp1" ]; then 50 | # The reason we don't just use `cargo prove build` from the SP1 CLI is we need to pass a --features ... 51 | # flag to select between sp1 and risc0. 52 | RUSTFLAGS="-C passes=lower-atomic -C link-arg=-Ttext=0x00200800 -C panic=abort" \ 53 | RUSTUP_TOOLCHAIN=succinct \ 54 | CARGO_BUILD_TARGET=riscv32im-succinct-zkvm-elf \ 55 | cargo build --release --ignore-rust-version --features $2 56 | fi 57 | # If the prover is risc0, then build the program. 58 | if [ "$2" == "risc0" ]; then 59 | echo "Building Risc0" 60 | CC=gcc CC_riscv32im_risc0_zkvm_elf=~/.risc0/cpp/bin/riscv32-unknown-elf-gcc RUSTFLAGS="-C passes=loweratomic -C link-arg=-Ttext=0x00200800 -C panic=abort" RISC0_FEATURE_bigint2=1 cargo +risc0 build --release --locked --target riscv32im-risc0-zkvm-elf --manifest-path Cargo.toml --features risc0 61 | fi 62 | 63 | cd ../../ 64 | 65 | # If buildOnly flag is set, exit here 66 | if [ "$6" == "buildOnly" ]; then 67 | echo "Build completed. Exiting due to buildOnly flag." 68 | exit 0 69 | fi 70 | 71 | echo "Running eval script" 72 | 73 | # Detect whether we're on an instance with a GPU. 74 | if nvidia-smi > /dev/null 2>&1; then 75 | GPU_EXISTS=true 76 | else 77 | GPU_EXISTS=false 78 | fi 79 | 80 | # Check for AVX-512 support 81 | if lscpu | grep -q avx512; then 82 | # If AVX-512 is supported, add the specific features to RUSTFLAGS 83 | export RUSTFLAGS="-C target-cpu=native -C target-feature=+avx512ifma,+avx512vl" 84 | else 85 | # If AVX-512 is not supported, just set target-cpu=native 86 | export RUSTFLAGS="-C target-cpu=native" 87 | fi 88 | 89 | # Set the logging level. 90 | export RUST_LOG=debug 91 | 92 | # Determine the features based on GPU existence. 93 | if [ "$GPU_EXISTS" = true ]; then 94 | FEATURES="cuda" 95 | else 96 | FEATURES="default" 97 | fi 98 | 99 | if [ "$2" == "risc0" ]; then 100 | if [ "$GPU_EXISTS" = true ]; then 101 | FEATURES="risc0, cuda" 102 | else 103 | FEATURES="risc0" 104 | fi 105 | fi 106 | 107 | if [ $TRACE_FILE ]; then 108 | echo "Setting TRACE_FILE=$TRACE_FILE" 109 | export TRACE_FILE=$TRACE_FILE 110 | fi 111 | 112 | if [ $TRACE_SAMPLE_RATE ]; then 113 | export TRACE_SAMPLE_RATE=$TRACE_SAMPLE_RATE 114 | fi 115 | 116 | # Run the benchmark and capture its exit status 117 | RISC0_INFO=1 RUST_LOG=info CUDA_VISIBLE_DEVICES=0 SP1_DISABLE_PROGRAM_CACHE=true cargo run \ 118 | -p sp1-benchmarks-eval \ 119 | --release \ 120 | --no-default-features \ 121 | --features "$FEATURES" \ 122 | -- \ 123 | --program "$1" \ 124 | --prover "$2" \ 125 | --hashfn "$3" \ 126 | --shard-size "$4" \ 127 | --filename "$5" \ 128 | ${6:+--block-number $6} 129 | 130 | exit $? 131 | -------------------------------------------------------------------------------- /eval/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "sp1-benchmarks-eval" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [build-dependencies] 7 | vergen = { version = "8", default-features = false, features = [ 8 | "build", 9 | "git", 10 | "git2", 11 | ] } 12 | 13 | [dependencies] 14 | clap = { version = "4.5.9", features = ["derive"] } 15 | csv = "1.3.0" 16 | bincode = "1.3.3" 17 | serde_json = "1.0" 18 | chrono = "0.4.38" 19 | 20 | # sp1 21 | sp1-prover = { version = "4.0.0-rc.10", features = ["native-gnark"] } 22 | sp1-core-executor = { version = "4.0.0-rc.10", features = ["profiling"] } 23 | sp1-core-machine = { version = "4.0.0-rc.10" } 24 | sp1-cuda = { version = "4.0.0-rc.10", optional = true } 25 | sp1-stark = { version = "4.0.0-rc.10" } 26 | sp1-sdk = { version = "4.0.0-rc.10", features = ["native-gnark"] } 27 | 28 | # sp1-prover = { path = "../../sp1/crates/prover", features = ["native-gnark"] } 29 | # sp1-core-executor = { path = "../../sp1/crates/core/executor" } 30 | # sp1-core-machine = { path = "../../sp1/crates/core/machine" } 31 | # sp1-cuda = { path = "../../sp1/crates/cuda", optional = true } 32 | # sp1-stark = { path = "../../sp1/crates/stark" } 33 | # sp1-sdk = { path = "../../sp1/crates/sdk" } 34 | 35 | # risc0 36 | risc0-zkvm = { version = "=1.2.1", default-features = false, features = [ 37 | "prove", 38 | "unstable", 39 | ], optional = true } 40 | risc0-groth16 = { version = "=1.2.1", optional = true } 41 | 42 | # sp1-reth 43 | sp1-reth-primitives = { git = "https://github.com/succinctlabs/sp1-reth.git", branch = "john/update-for-v1" } 44 | ed25519-dalek = { version = "2.1.1", features = ["digest", "rand_core", "serde", "signature"] } 45 | k256 = { version = "=0.13.3", features = ["serde"] } 46 | rand = "0.8.5" 47 | rand_core = "0.6.4" 48 | serde = { version = "1.0.215", features = ["derive"] } 49 | 50 | [features] 51 | default = [] 52 | sp1 = [] 53 | cuda = ["dep:sp1-cuda", "risc0-zkvm?/cuda"] 54 | risc0 = ["dep:risc0-zkvm", "dep:risc0-groth16"] 55 | -------------------------------------------------------------------------------- /eval/blocks/17106222.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/succinctlabs/zkvm-perf/861cc5c18e3e31ae080640877642ce818e7eaff4/eval/blocks/17106222.bin -------------------------------------------------------------------------------- /eval/blocks/18635849.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/succinctlabs/zkvm-perf/861cc5c18e3e31ae080640877642ce818e7eaff4/eval/blocks/18635849.bin -------------------------------------------------------------------------------- /eval/blocks/19409717.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/succinctlabs/zkvm-perf/861cc5c18e3e31ae080640877642ce818e7eaff4/eval/blocks/19409717.bin -------------------------------------------------------------------------------- /eval/blocks/19409768.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/succinctlabs/zkvm-perf/861cc5c18e3e31ae080640877642ce818e7eaff4/eval/blocks/19409768.bin -------------------------------------------------------------------------------- /eval/blocks/19422264.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/succinctlabs/zkvm-perf/861cc5c18e3e31ae080640877642ce818e7eaff4/eval/blocks/19422264.bin -------------------------------------------------------------------------------- /eval/blocks/19425663.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/succinctlabs/zkvm-perf/861cc5c18e3e31ae080640877642ce818e7eaff4/eval/blocks/19425663.bin -------------------------------------------------------------------------------- /eval/blocks/19425776.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/succinctlabs/zkvm-perf/861cc5c18e3e31ae080640877642ce818e7eaff4/eval/blocks/19425776.bin -------------------------------------------------------------------------------- /eval/blocks/19426396.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/succinctlabs/zkvm-perf/861cc5c18e3e31ae080640877642ce818e7eaff4/eval/blocks/19426396.bin -------------------------------------------------------------------------------- /eval/blocks/19426535.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/succinctlabs/zkvm-perf/861cc5c18e3e31ae080640877642ce818e7eaff4/eval/blocks/19426535.bin -------------------------------------------------------------------------------- /eval/blocks/19426587.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/succinctlabs/zkvm-perf/861cc5c18e3e31ae080640877642ce818e7eaff4/eval/blocks/19426587.bin -------------------------------------------------------------------------------- /eval/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | vergen::EmitBuilder::builder().build_timestamp().git_sha(true).emit().unwrap(); 3 | } 4 | -------------------------------------------------------------------------------- /eval/src/main.rs: -------------------------------------------------------------------------------- 1 | mod risc0; 2 | mod sp1; 3 | mod types; 4 | mod utils; 5 | 6 | use std::{ 7 | fs::{create_dir_all, OpenOptions}, 8 | path::PathBuf, 9 | }; 10 | 11 | use clap::{command, Parser}; 12 | use csv::WriterBuilder; 13 | use serde::Serialize; 14 | use types::*; 15 | 16 | /// The argument passed through the CLI. 17 | #[derive(Parser, Clone)] 18 | #[command(about = "Evaluate the performance of a zkVM on a program.")] 19 | pub struct EvalArgs { 20 | #[arg(long)] 21 | program: ProgramId, 22 | #[arg(long)] 23 | prover: ProverId, 24 | #[arg(long)] 25 | hashfn: HashFnId, 26 | #[arg(long)] 27 | shard_size: u64, 28 | #[arg(long)] 29 | filename: String, 30 | #[arg(long)] 31 | block_number: Option, 32 | #[arg(long)] 33 | groth16: bool, 34 | #[arg(long)] 35 | plonk: bool, 36 | } 37 | 38 | /// The performance report of a zkVM on a program. 39 | #[derive(Debug, Serialize, Default)] 40 | pub struct PerformanceReport { 41 | pub priority: usize, 42 | /// The program that is being evaluated. 43 | pub program: String, 44 | /// The prover that is being evaluated. 45 | pub prover: String, 46 | /// The hash function that is being evaluated. 47 | pub hashfn: String, 48 | /// The shard size that is being evaluated. 49 | pub shard_size: u64, 50 | /// The number of shards. 51 | pub shards: usize, 52 | /// The reported number of cycles. 53 | /// 54 | /// Note that this number may vary based on the zkVM. 55 | pub cycles: u64, 56 | /// The reported speed in cycles per second. 57 | pub speed: f64, 58 | /// The reported duration of the execution in seconds. 59 | pub execution_duration: f64, 60 | /// The reported duration of the prover in seconds. 61 | pub prove_duration: f64, 62 | 63 | /// The reported duration of the core proving time in seconds. 64 | pub core_prove_duration: f64, 65 | /// The reported duration of the verifier in seconds. 66 | pub core_verify_duration: f64, 67 | /// The size of the core proof. 68 | pub core_proof_size: usize, 69 | /// The speed of the core proving time in KHz. 70 | pub core_khz: f64, 71 | 72 | /// The reported duration of the recursive proving time in seconds. 73 | pub compress_prove_duration: f64, 74 | /// The reported duration of the verifier in seconds. 75 | pub compress_verify_duration: f64, 76 | /// The size of the recursive proof in bytes. 77 | pub compress_proof_size: usize, 78 | 79 | /// The reported duration of the shrink proving time in seconds. 80 | pub shrink_prove_duration: f64, 81 | /// The reported duration of the wrap proving time in seconds. 82 | pub wrap_prove_duration: f64, 83 | /// The reported duration of the groth16 proving time in seconds. 84 | pub groth16_prove_duration: f64, 85 | /// The reported duration of the plonk proving time in seconds. 86 | pub plonk_prove_duration: f64, 87 | 88 | /// The overall speed in KHz. 89 | pub overall_khz: f64, 90 | /// The number of hashes per second 91 | pub hashes_per_second: Option, 92 | /// The number of bytes hashed per second 93 | pub hash_bytes_per_second: Option, 94 | /// The gas used by the program (if RSP) 95 | pub gas: Option, 96 | } 97 | 98 | fn main() { 99 | // Setup the logger. 100 | sp1_core_machine::utils::setup_logger(); 101 | 102 | let args = EvalArgs::parse(); 103 | 104 | // Select the correct implementation based on the prover. 105 | let report = match args.prover { 106 | ProverId::Risc0 => risc0::Risc0Evaluator::eval(&args), 107 | ProverId::SP1 => sp1::SP1Evaluator::eval(&args), 108 | }; 109 | 110 | // Create the results directory if it doesn't exist. 111 | let results_dir = PathBuf::from("benchmarks"); 112 | create_dir_all(&results_dir).unwrap(); 113 | 114 | // Create the file. 115 | let filename = format!("{}_{}.csv", args.filename, env!("VERGEN_GIT_SHA")); 116 | let path = results_dir.join(filename); 117 | let file = OpenOptions::new().create(true).append(true).open(path.clone()).unwrap(); 118 | 119 | // Write the row and the header, if needed. 120 | let mut writer = WriterBuilder::new().from_writer(&file); 121 | if file.metadata().unwrap().len() == 0 { 122 | writer 123 | .write_record(&[ 124 | "program", 125 | "prover", 126 | "hashfn", 127 | "shard_size", 128 | "shards", 129 | "cycles", 130 | "speed", 131 | "execution_duration", 132 | "prove_duration", 133 | "core_prove_duration", 134 | "core_verify_duration", 135 | "core_proof_size", 136 | "core_khz", 137 | "compress_prove_duration", 138 | "compress_verify_duration", 139 | "compress_proof_size", 140 | "overall_khz", 141 | "priority", 142 | "hashes_per_second", 143 | "hash_bytes_per_second", 144 | "gas", 145 | "shrink_prove_duration", 146 | "wrap_prove_duration", 147 | "groth16_prove_duration", 148 | "plonk_prove_duration", 149 | ]) 150 | .unwrap(); 151 | } 152 | writer 153 | .serialize(&[ 154 | report.program, 155 | report.prover, 156 | report.hashfn, 157 | report.shard_size.to_string(), 158 | report.shards.to_string(), 159 | report.cycles.to_string(), 160 | report.speed.to_string(), 161 | report.execution_duration.to_string(), 162 | report.prove_duration.to_string(), 163 | report.core_prove_duration.to_string(), 164 | report.core_verify_duration.to_string(), 165 | report.core_proof_size.to_string(), 166 | report.core_khz.to_string(), 167 | report.compress_prove_duration.to_string(), 168 | report.compress_verify_duration.to_string(), 169 | report.compress_proof_size.to_string(), 170 | report.overall_khz.to_string(), 171 | report.priority.to_string(), 172 | report.hashes_per_second.map(|x| x.to_string()).unwrap_or_default(), 173 | report.hash_bytes_per_second.map(|x| x.to_string()).unwrap_or_default(), 174 | report.gas.map(|x| x.to_string()).unwrap_or_default(), 175 | report.shrink_prove_duration.to_string(), 176 | report.wrap_prove_duration.to_string(), 177 | report.groth16_prove_duration.to_string(), 178 | report.plonk_prove_duration.to_string(), 179 | ]) 180 | .unwrap(); 181 | writer.flush().unwrap(); 182 | 183 | let latest_filename = "benchmarks_latest.csv"; 184 | let latest_path = results_dir.join(latest_filename); 185 | std::fs::copy(&path, &latest_path).unwrap(); 186 | } 187 | -------------------------------------------------------------------------------- /eval/src/types.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::{Display, Formatter}; 2 | 3 | /// An identifier used to select the program to evaluate. 4 | #[derive(clap::ValueEnum, Clone, PartialEq)] 5 | #[clap(rename_all = "kebab_case")] 6 | pub enum ProgramId { 7 | // Loop. 8 | Loop10k, 9 | Loop100k, 10 | Loop1m, 11 | Loop3m, 12 | Loop10m, 13 | Loop30m, 14 | Loop100m, 15 | Loop300m, 16 | 17 | // Fibonacci. 18 | Fibonacci20k, 19 | Fibonacci200k, 20 | Fibonacci2m, 21 | Fibonacci4m, 22 | Fibonacci20m, 23 | Fibonacci40m, 24 | Fibonacci200m, 25 | Fibonacci400m, 26 | Fibonacci1b, 27 | Fibonacci2b, 28 | Fibonacci4b, 29 | 30 | // SHA-256. 31 | Sha256100kb, 32 | Sha256300kb, 33 | Sha2561mb, 34 | Sha2563mb, 35 | Sha25610mb, 36 | 37 | // Keccak-256. 38 | Keccak256100kb, 39 | Keccak256300kb, 40 | Keccak2561mb, 41 | Keccak2563mb, 42 | Keccak25610mb, 43 | 44 | // SSZ Withdrawals. 45 | SSZWithdrawals, 46 | 47 | // Tendermint. 48 | Tendermint, 49 | 50 | // RSP 51 | Rsp20526626, 52 | Rsp20526627, 53 | Rsp20526628, 54 | Rsp20526629, 55 | Rsp20526630, 56 | Rsp20528708, 57 | Rsp20528709, 58 | Rsp20528710, 59 | Rsp20528711, 60 | Rsp20528712, 61 | 62 | // Signatures 63 | ECDSAVerify, 64 | EDDSAVerify, 65 | 66 | Helios, 67 | 68 | Groth16ProofVerify, 69 | 70 | ZKEmail, 71 | } 72 | 73 | impl ProgramId { 74 | /// The "priority" of a program is used to sort the programs in the performance report. 75 | /// 76 | /// The higher the priority, the more work the proof requires. 77 | pub(crate) fn priority(&self) -> usize { 78 | match self { 79 | // Loop 80 | ProgramId::Loop10k => 1, 81 | ProgramId::Loop100k => 2, 82 | ProgramId::Loop1m => 3, 83 | ProgramId::Loop3m => 4, 84 | ProgramId::Loop10m => 5, 85 | ProgramId::Loop30m => 6, 86 | ProgramId::Loop100m => 7, 87 | ProgramId::Loop300m => 8, 88 | 89 | // Fibonacci 90 | ProgramId::Fibonacci20k => 1, 91 | ProgramId::Fibonacci200k => 2, 92 | ProgramId::Fibonacci2m => 3, 93 | ProgramId::Fibonacci4m => 4, 94 | ProgramId::Fibonacci20m => 5, 95 | ProgramId::Fibonacci40m => 6, 96 | ProgramId::Fibonacci200m => 7, 97 | ProgramId::Fibonacci400m => 8, 98 | ProgramId::Fibonacci1b => 9, 99 | ProgramId::Fibonacci2b => 10, 100 | ProgramId::Fibonacci4b => 11, 101 | 102 | // SHA-256 103 | ProgramId::Sha256100kb => 1, 104 | ProgramId::Sha256300kb => 2, 105 | ProgramId::Sha2561mb => 3, 106 | ProgramId::Sha2563mb => 4, 107 | ProgramId::Sha25610mb => 5, 108 | 109 | // Keccak-256 110 | ProgramId::Keccak256100kb => 1, 111 | ProgramId::Keccak256300kb => 2, 112 | ProgramId::Keccak2561mb => 3, 113 | ProgramId::Keccak2563mb => 4, 114 | ProgramId::Keccak25610mb => 5, 115 | 116 | // SSZ Withdrawals 117 | ProgramId::SSZWithdrawals => 1, 118 | 119 | // Tendermint 120 | ProgramId::Tendermint => 1, 121 | 122 | // RSP 123 | ProgramId::Rsp20526626 => 1, 124 | ProgramId::Rsp20526627 => 1, 125 | ProgramId::Rsp20526628 => 1, 126 | ProgramId::Rsp20526629 => 1, 127 | ProgramId::Rsp20526630 => 1, 128 | ProgramId::Rsp20528708 => 1, 129 | ProgramId::Rsp20528709 => 1, 130 | ProgramId::Rsp20528710 => 1, 131 | ProgramId::Rsp20528711 => 1, 132 | ProgramId::Rsp20528712 => 1, 133 | 134 | // Signatures 135 | ProgramId::ECDSAVerify => 1, 136 | ProgramId::EDDSAVerify => 1, 137 | 138 | ProgramId::Helios => 1, 139 | 140 | ProgramId::Groth16ProofVerify => 1, 141 | 142 | ProgramId::ZKEmail => 1, 143 | } 144 | } 145 | } 146 | 147 | /// An identifier used to select the prover to evaluate. 148 | #[derive(clap::ValueEnum, Clone, PartialEq)] 149 | pub enum ProverId { 150 | Risc0, 151 | SP1, 152 | } 153 | 154 | /// An identifier used to select the hash function to evaluate. 155 | #[derive(clap::ValueEnum, Clone, PartialEq)] 156 | pub enum HashFnId { 157 | Sha256, 158 | Poseidon, 159 | Blake3, 160 | Keccak256, 161 | } 162 | 163 | impl Display for ProgramId { 164 | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { 165 | match self { 166 | ProgramId::Loop10k => write!(f, "loop-10k"), 167 | ProgramId::Loop100k => write!(f, "loop-100k"), 168 | ProgramId::Loop1m => write!(f, "loop-1m"), 169 | ProgramId::Loop3m => write!(f, "loop-3m"), 170 | ProgramId::Loop10m => write!(f, "loop-10m"), 171 | ProgramId::Loop30m => write!(f, "loop-30m"), 172 | ProgramId::Loop100m => write!(f, "loop-100m"), 173 | ProgramId::Loop300m => write!(f, "loop-300m"), 174 | ProgramId::Fibonacci20k => write!(f, "fibonacci-20k"), 175 | ProgramId::Fibonacci200k => write!(f, "fibonacci-200k"), 176 | ProgramId::Fibonacci2m => write!(f, "fibonacci-2m"), 177 | ProgramId::Fibonacci4m => write!(f, "fibonacci-4m"), 178 | ProgramId::Fibonacci20m => write!(f, "fibonacci-20m"), 179 | ProgramId::Fibonacci40m => write!(f, "fibonacci-40m"), 180 | ProgramId::Fibonacci200m => write!(f, "fibonacci-200m"), 181 | ProgramId::Fibonacci400m => write!(f, "fibonacci-400m"), 182 | ProgramId::Fibonacci1b => write!(f, "fibonacci-1b"), 183 | ProgramId::Fibonacci2b => write!(f, "fibonacci-2b"), 184 | ProgramId::Fibonacci4b => write!(f, "fibonacci-4b"), 185 | ProgramId::Sha256100kb => write!(f, "sha256-100kb"), 186 | ProgramId::Sha256300kb => write!(f, "sha256-300kb"), 187 | ProgramId::Sha2561mb => write!(f, "sha256-1mb"), 188 | ProgramId::Sha2563mb => write!(f, "sha256-3mb"), 189 | ProgramId::Sha25610mb => write!(f, "sha256-10mb"), 190 | ProgramId::Keccak256100kb => write!(f, "keccak256-100kb"), 191 | ProgramId::Keccak256300kb => write!(f, "keccak256-300kb"), 192 | ProgramId::Keccak2561mb => write!(f, "keccak256-1mb"), 193 | ProgramId::Keccak2563mb => write!(f, "keccak256-3mb"), 194 | ProgramId::Keccak25610mb => write!(f, "keccak256-10mb"), 195 | ProgramId::SSZWithdrawals => write!(f, "ssz-withdrawals"), 196 | ProgramId::Tendermint => write!(f, "tendermint"), 197 | ProgramId::Rsp20526626 => write!(f, "rsp-20526626"), 198 | ProgramId::Rsp20526627 => write!(f, "rsp-20526627"), 199 | ProgramId::Rsp20526628 => write!(f, "rsp-20526628"), 200 | ProgramId::Rsp20526629 => write!(f, "rsp-20526629"), 201 | ProgramId::Rsp20526630 => write!(f, "rsp-20526630"), 202 | ProgramId::Rsp20528708 => write!(f, "rsp-20528708"), 203 | ProgramId::Rsp20528709 => write!(f, "rsp-20528709"), 204 | ProgramId::Rsp20528710 => write!(f, "rsp-20528710"), 205 | ProgramId::Rsp20528711 => write!(f, "rsp-20528711"), 206 | ProgramId::Rsp20528712 => write!(f, "rsp-20528712"), 207 | ProgramId::ECDSAVerify => write!(f, "ecdsa-verify"), 208 | ProgramId::EDDSAVerify => write!(f, "eddsa-verify"), 209 | ProgramId::Helios => write!(f, "helios"), 210 | ProgramId::Groth16ProofVerify => write!(f, "groth16-proof-verify"), 211 | ProgramId::ZKEmail => write!(f, "zk-email"), 212 | } 213 | } 214 | } 215 | 216 | impl Display for ProverId { 217 | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { 218 | match self { 219 | ProverId::Risc0 => write!(f, "risc0"), 220 | ProverId::SP1 => write!(f, "sp1"), 221 | } 222 | } 223 | } 224 | 225 | impl Display for HashFnId { 226 | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { 227 | match self { 228 | HashFnId::Sha256 => write!(f, "sha-256"), 229 | HashFnId::Poseidon => write!(f, "poseidon"), 230 | HashFnId::Blake3 => write!(f, "blake3"), 231 | HashFnId::Keccak256 => write!(f, "keccak256"), 232 | } 233 | } 234 | } 235 | -------------------------------------------------------------------------------- /eval/src/utils.rs: -------------------------------------------------------------------------------- 1 | use core::time; 2 | use std::{ 3 | env, fs, 4 | time::{Duration, Instant}, 5 | }; 6 | 7 | use k256::ecdsa::signature::SignerMut; 8 | use sp1_reth_primitives::SP1RethInput; 9 | 10 | use crate::{EvalArgs, ProgramId, ProverId}; 11 | 12 | pub fn get_elf(args: &EvalArgs) -> String { 13 | let mut program_dir = args.program.to_string(); 14 | if args.program == ProgramId::Tendermint { 15 | program_dir += "-"; 16 | program_dir += args.prover.to_string().as_str(); 17 | } 18 | if program_dir.starts_with("loop") { 19 | program_dir = "loop".to_string(); 20 | } 21 | if program_dir.starts_with("fibonacci") { 22 | program_dir = "fibonacci".to_string(); 23 | } 24 | if program_dir.starts_with("sha256") { 25 | program_dir = "sha256".to_string(); 26 | program_dir += "-"; 27 | program_dir += args.prover.to_string().as_str(); 28 | } 29 | if program_dir.starts_with("keccak256") { 30 | program_dir = "keccak256".to_string(); 31 | program_dir += "-"; 32 | program_dir += args.prover.to_string().as_str(); 33 | } 34 | if program_dir.starts_with("rsp") { 35 | program_dir = "rsp".to_string(); 36 | program_dir += "-"; 37 | program_dir += args.prover.to_string().as_str(); 38 | } 39 | if program_dir.starts_with("ecdsa-verify") { 40 | program_dir += "-"; 41 | program_dir += args.prover.to_string().as_str(); 42 | } 43 | if program_dir.starts_with("eddsa-verify") { 44 | program_dir += "-"; 45 | program_dir += args.prover.to_string().as_str(); 46 | } 47 | if program_dir.starts_with("helios") { 48 | program_dir += "-"; 49 | program_dir += args.prover.to_string().as_str(); 50 | } 51 | if program_dir.starts_with("groth16-proof-verify") { 52 | program_dir = "groth".to_string(); 53 | program_dir += "-"; 54 | program_dir += args.prover.to_string().as_str(); 55 | } 56 | if program_dir.starts_with("zk-email") { 57 | program_dir = "zk-email".to_string(); 58 | program_dir += "-"; 59 | program_dir += args.prover.to_string().as_str(); 60 | } 61 | 62 | let current_dir = env::current_dir().expect("Failed to get current working directory"); 63 | 64 | let mut elf_path = current_dir.join(format!( 65 | "programs/{}/target/riscv32im-succinct-zkvm-elf/release/{}", 66 | program_dir, program_dir 67 | )); 68 | 69 | if args.prover == ProverId::Risc0 { 70 | elf_path = current_dir.join(format!( 71 | "programs/{}/target/riscv32im-risc0-zkvm-elf/release/{}", 72 | program_dir, program_dir 73 | )); 74 | } 75 | 76 | let elf_path_str = elf_path.to_str().expect("Failed to convert path to string").to_string(); 77 | println!("elf path: {}", elf_path_str); 78 | elf_path_str 79 | } 80 | 81 | pub fn time_operation T>(operation: F) -> (T, time::Duration) { 82 | let start = Instant::now(); 83 | let result = operation(); 84 | let duration = start.elapsed(); 85 | (result, duration) 86 | } 87 | 88 | pub fn gas_amount(program: &ProgramId) -> Option { 89 | let amount = match program { 90 | ProgramId::Rsp20526626 => 12_121_809, 91 | ProgramId::Rsp20526627 => 16_515_842, 92 | ProgramId::Rsp20526628 => 13_311_631, 93 | ProgramId::Rsp20526629 => 16_995_405, 94 | ProgramId::Rsp20526630 => 16_936_272, 95 | ProgramId::Rsp20528708 => 13_218_606, 96 | ProgramId::Rsp20528709 => 16_512_503, 97 | ProgramId::Rsp20528710 => 11_570_190, 98 | ProgramId::Rsp20528711 => 12_942_861, 99 | ProgramId::Rsp20528712 => 14_753_755, 100 | _ => return None, 101 | }; 102 | 103 | Some(amount) 104 | } 105 | 106 | /// The hashes per second are given by the block size of the hash function 107 | pub fn hashes_per_second(program: &ProgramId, core_compress_duration: Duration) -> Option { 108 | let word_size_bytes: u64 = match program { 109 | ProgramId::Sha256100kb 110 | | ProgramId::Sha256300kb 111 | | ProgramId::Sha2561mb 112 | | ProgramId::Sha2563mb 113 | | ProgramId::Sha25610mb => 64, 114 | ProgramId::Keccak256100kb 115 | | ProgramId::Keccak256300kb 116 | | ProgramId::Keccak2561mb 117 | | ProgramId::Keccak2563mb 118 | | ProgramId::Keccak25610mb => 136, 119 | _ => return None, 120 | }; 121 | 122 | let num_of_bytes = hash_input_size_bytes(program).expect("We should have an input size if we have a word size"); 123 | let hashes_total = num_of_bytes / word_size_bytes; 124 | 125 | let duration = core_compress_duration.as_secs_f64(); 126 | 127 | Some(hashes_total as f64 / duration) 128 | } 129 | 130 | /// The number of bytes hashed per second 131 | /// 132 | /// Given by dividing the number of bytes hashed by the duration of the proving 133 | pub fn hash_bytes_per_second(program: &ProgramId, core_compress_duration: Duration) -> Option { 134 | let num_of_bytes = hash_input_size_bytes(program)?; 135 | 136 | let num_of_bytes = num_of_bytes as f64; 137 | 138 | let duration = core_compress_duration.as_secs_f64(); 139 | 140 | Some(num_of_bytes / duration) 141 | } 142 | 143 | /// The number of bytes we pass in as input for each program type 144 | pub fn hash_input_size_bytes(program: &ProgramId) -> Option { 145 | let num_of_bytes = match program { 146 | ProgramId::Sha256100kb => 102400, 147 | ProgramId::Sha256300kb => 102400 * 3, 148 | ProgramId::Sha2561mb => 1048576, 149 | ProgramId::Sha2563mb => 1048576 * 3, 150 | ProgramId::Sha25610mb => 1048576 * 10, 151 | ProgramId::Keccak256100kb => 102400, 152 | ProgramId::Keccak256300kb => 102400 * 3, 153 | ProgramId::Keccak2561mb => 1048576, 154 | ProgramId::Keccak2563mb => 1048576 * 3, 155 | ProgramId::Keccak25610mb => 1048576 * 10, 156 | _ => return None, 157 | }; 158 | 159 | Some(num_of_bytes) 160 | } 161 | 162 | // for now just for RSP 163 | //pub fn raw_input(program: &ProgramId) -> Option<&[u8]> { 164 | // let raw = match program { 165 | // ProgramId::Rsp20526626 => { 166 | // include_bytes!("../../fixtures/20526626.bin") 167 | // } 168 | // ProgramId::Rsp20526627 => { 169 | // include_bytes!("../../fixtures/20526627.bin") 170 | // } 171 | // ProgramId::Rsp20526628 => { 172 | // include_bytes!("../../fixtures/20526628.bin") 173 | // } 174 | // ProgramId::Rsp20526629 => { 175 | // include_bytes!("../../fixtures/20526629.bin") 176 | // } 177 | // ProgramId::Rsp20526630 => { 178 | // include_bytes!("../../fixtures/20526630.bin") 179 | // } 180 | // ProgramId::Rsp20528708 => { 181 | // include_bytes!("../../fixtures/20528708.bin") 182 | // } 183 | // ProgramId::Rsp20528709 => { 184 | // include_bytes!("../../fixtures/20528709.bin") 185 | // } 186 | // ProgramId::Rsp20528710 => { 187 | // include_bytes!("../../fixtures/20528710.bin") 188 | // } 189 | // ProgramId::Rsp20528711 => { 190 | // include_bytes!("../../fixtures/20528711.bin") 191 | // } 192 | // ProgramId::Rsp20528712 => { 193 | // include_bytes!("../../fixtures/20528712.bin") 194 | // }, 195 | // _ => return None, 196 | // }; 197 | // 198 | // Some(raw) 199 | //} 200 | 201 | 202 | pub fn rand_ecdsa_signature() -> (k256::EncodedPoint, Vec, k256::ecdsa::Signature) { 203 | use rand::rngs::OsRng; 204 | use k256::ecdsa::{SigningKey, VerifyingKey}; 205 | 206 | let mut signing_key = SigningKey::random(&mut OsRng); 207 | let verifying_key = VerifyingKey::from(&signing_key); 208 | 209 | let message = b"Hello, world!"; 210 | let signature = signing_key.sign(message); 211 | 212 | (verifying_key.to_encoded_point(true), message.to_vec(), signature) 213 | } 214 | 215 | pub fn rand_eddsa_signature() -> (ed25519_dalek::VerifyingKey, Vec, ed25519_dalek::Signature) { 216 | use rand::rngs::OsRng; 217 | use ed25519_dalek::{SigningKey, Signer}; 218 | 219 | let signing_key = SigningKey::generate(&mut OsRng); 220 | let message = b"Hello, world!"; 221 | let signature = signing_key.sign(message); 222 | 223 | (signing_key.verifying_key(), message.to_vec(), signature) 224 | } 225 | -------------------------------------------------------------------------------- /fixtures/20526626.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/succinctlabs/zkvm-perf/861cc5c18e3e31ae080640877642ce818e7eaff4/fixtures/20526626.bin -------------------------------------------------------------------------------- /fixtures/20526627.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/succinctlabs/zkvm-perf/861cc5c18e3e31ae080640877642ce818e7eaff4/fixtures/20526627.bin -------------------------------------------------------------------------------- /fixtures/20526628.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/succinctlabs/zkvm-perf/861cc5c18e3e31ae080640877642ce818e7eaff4/fixtures/20526628.bin -------------------------------------------------------------------------------- /fixtures/20526629.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/succinctlabs/zkvm-perf/861cc5c18e3e31ae080640877642ce818e7eaff4/fixtures/20526629.bin -------------------------------------------------------------------------------- /fixtures/20526630.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/succinctlabs/zkvm-perf/861cc5c18e3e31ae080640877642ce818e7eaff4/fixtures/20526630.bin -------------------------------------------------------------------------------- /fixtures/20528708.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/succinctlabs/zkvm-perf/861cc5c18e3e31ae080640877642ce818e7eaff4/fixtures/20528708.bin -------------------------------------------------------------------------------- /fixtures/20528709.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/succinctlabs/zkvm-perf/861cc5c18e3e31ae080640877642ce818e7eaff4/fixtures/20528709.bin -------------------------------------------------------------------------------- /fixtures/20528710.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/succinctlabs/zkvm-perf/861cc5c18e3e31ae080640877642ce818e7eaff4/fixtures/20528710.bin -------------------------------------------------------------------------------- /fixtures/20528711.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/succinctlabs/zkvm-perf/861cc5c18e3e31ae080640877642ce818e7eaff4/fixtures/20528711.bin -------------------------------------------------------------------------------- /fixtures/20528712.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/succinctlabs/zkvm-perf/861cc5c18e3e31ae080640877642ce818e7eaff4/fixtures/20528712.bin -------------------------------------------------------------------------------- /fixtures/helios/proof_inputs.cbor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/succinctlabs/zkvm-perf/861cc5c18e3e31ae080640877642ce818e7eaff4/fixtures/helios/proof_inputs.cbor -------------------------------------------------------------------------------- /fixtures/risc0/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "pi_a": [ 3 | "14607323418175493877649123188559106090712031035853367405566902242087679079026", 4 | "15486828600118019415977500325069600489417487454177260460169822862084509509706", 5 | "1" 6 | ], 7 | "pi_b": [ 8 | [ 9 | "12483720895199157233703897096660725461581079966613691771265994952250389556089", 10 | "9949178090876592045635355531407531373361768427796039917325698685667408594949" 11 | ], 12 | [ 13 | "21855535729070827943043225878781025263461213787082455238155875177785152064642", 14 | "4831913446371464672162217946864208119999358464561356521338566530707660851901" 15 | ], 16 | [ 17 | "1", 18 | "0" 19 | ] 20 | ], 21 | "pi_c": [ 22 | "14245434144847865220734832888275758519142024418579892293721854052257185804081", 23 | "12409292328417071347651065907389652805822665293133528391908629849906022830324", 24 | "1" 25 | ], 26 | "protocol": "groth16", 27 | "curve": "bn128" 28 | } 29 | -------------------------------------------------------------------------------- /fixtures/risc0/public.json: -------------------------------------------------------------------------------- 1 | [ 2 | "0", 3 | "0", 4 | "0", 5 | "0", 6 | "0", 7 | "6", 8 | "0", 9 | "0", 10 | "0", 11 | "0", 12 | "0", 13 | "7", 14 | "2", 15 | "0", 16 | "0", 17 | "8", 18 | "0", 19 | "0", 20 | "9", 21 | "0", 22 | "6", 23 | "8", 24 | "0", 25 | "0", 26 | "0", 27 | "1", 28 | "0", 29 | "3", 30 | "0", 31 | "0", 32 | "7", 33 | "0", 34 | "0", 35 | "0", 36 | "2", 37 | "9", 38 | "0", 39 | "0", 40 | "0", 41 | "0", 42 | "0", 43 | "0", 44 | "0", 45 | "0", 46 | "0", 47 | "4", 48 | "0", 49 | "0", 50 | "5", 51 | "0", 52 | "0", 53 | "0", 54 | "7", 55 | "0", 56 | "6", 57 | "5", 58 | "0", 59 | "1", 60 | "0", 61 | "0", 62 | "0", 63 | "0", 64 | "0", 65 | "8", 66 | "0", 67 | "1", 68 | "0", 69 | "5", 70 | "0", 71 | "3", 72 | "0", 73 | "0", 74 | "7", 75 | "9", 76 | "2", 77 | "0", 78 | "0", 79 | "0", 80 | "0", 81 | "0", 82 | "4" 83 | ] 84 | -------------------------------------------------------------------------------- /install-1.82-toolchain.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -euo pipefail 4 | 5 | # Constants 6 | RUSTUP_TOOLCHAIN_NAME="succinct" 7 | ROOT_DIR="$HOME/.sp1" 8 | TOOLCHAINS_DIR="$ROOT_DIR/toolchains" 9 | 10 | # Function to get the target triple 11 | get_target() { 12 | local target=$(rustc -vV | grep "host:" | awk '{print $2}') 13 | if [[ "$target" == *"-musl" ]]; then 14 | target="${target/musl/gnu}" 15 | fi 16 | echo "$target" 17 | } 18 | 19 | # Ensure Rust and Rustup are installed 20 | if ! command -v rustup &>/dev/null; then 21 | echo "Rust is not installed. Please install Rust from https://rustup.rs/ and try again." 22 | exit 1 23 | fi 24 | 25 | # Prepare directories 26 | mkdir -p "$ROOT_DIR" "$TOOLCHAINS_DIR" 27 | 28 | # Get target triple 29 | TARGET=$(get_target) 30 | TOOLCHAIN_ASSET_NAME="rust-toolchain-${TARGET}.tar.gz" 31 | TOOLCHAIN_ARCHIVE_PATH="$ROOT_DIR/$TOOLCHAIN_ASSET_NAME" 32 | TOOLCHAIN_URL="https://github.com/succinctlabs/rust/releases/download/v1.82.0/$TOOLCHAIN_ASSET_NAME" 33 | 34 | # Download the toolchain 35 | echo "Downloading toolchain from $TOOLCHAIN_URL..." 36 | curl -fSL "$TOOLCHAIN_URL" -o "$TOOLCHAIN_ARCHIVE_PATH" 37 | 38 | # Unpack the toolchain 39 | NEW_TOOLCHAIN_DIR="$TOOLCHAINS_DIR/1.82.0" 40 | mkdir -p "$NEW_TOOLCHAIN_DIR" 41 | echo "Unpacking toolchain to $NEW_TOOLCHAIN_DIR..." 42 | tar -xzf "$TOOLCHAIN_ARCHIVE_PATH" -C "$NEW_TOOLCHAIN_DIR" --strip-components=1 43 | 44 | # Link the toolchain to rustup 45 | echo "Linking toolchain to rustup as $RUSTUP_TOOLCHAIN_NAME..." 46 | rustup toolchain link "$RUSTUP_TOOLCHAIN_NAME" "$NEW_TOOLCHAIN_DIR" 47 | 48 | # Ensure permissions for binaries 49 | BIN_DIR="$NEW_TOOLCHAIN_DIR/bin" 50 | RUSTLIB_BIN_DIR="$NEW_TOOLCHAIN_DIR/lib/rustlib/$TARGET/bin" 51 | 52 | for DIR in "$BIN_DIR" "$RUSTLIB_BIN_DIR"; do 53 | if [[ -d "$DIR" ]]; then 54 | chmod -R 755 "$DIR" 55 | fi 56 | done 57 | 58 | echo "Toolchain installed and linked successfully." 59 | -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Exit immediately if a command exits with a non-zero status. 4 | set -e 5 | 6 | # Helper function to print an error message and exit. 7 | error_exit() { 8 | echo "Error: $1 failed with exit code $?. Exiting." 9 | exit 1 10 | } 11 | 12 | # Install Rust 13 | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y || error_exit "Installing Rust" 14 | source $HOME/.cargo/env 15 | 16 | # Install the nightly toolchain 17 | rustup toolchain install nightly --profile minimal -c rust-src || error_exit "Installing nightly toolchain" 18 | 19 | # Set the default toolchain to nightly 20 | rustup default nightly || error_exit "Setting default toolchain to nightly" 21 | 22 | # Install the Succinct toolchain 23 | curl -L https://sp1.succinct.xyz | bash || error_exit "Installing Succinct toolchain" 24 | export PATH="$PATH:$HOME/.sp1/bin" 25 | sp1up || error_exit "Updating Succinct toolchain" 26 | cargo prove --version || error_exit "Checking cargo prove version" 27 | 28 | # Install the Risc0 toolchain 29 | curl -L https://risczero.com/install | grep -v 'set -euo pipefail' | bash || error_exit "Installing Risc Zero toolchain" 30 | export PATH="$PATH:$HOME/.risc0/bin" 31 | rzup install || error_exit "Updating Risc Zero toolchain" 32 | cargo risczero --version || error_exit "Checking cargo risczero version" 33 | 34 | echo "All installations completed successfully." 35 | -------------------------------------------------------------------------------- /programs/ecdsa-verify-risc0/.gitignore: -------------------------------------------------------------------------------- 1 | Cargo.lock 2 | -------------------------------------------------------------------------------- /programs/ecdsa-verify-risc0/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | [package] 3 | name = "ecdsa-verify-risc0" 4 | version = "0.1.0" 5 | edition = "2021" 6 | 7 | [dependencies] 8 | hex-literal = "0.4" 9 | k256 = { version = "0.13.3", features = ["arithmetic", "serde", "expose-field", "std", "ecdsa"], default_features = false } 10 | risc0-zkvm = { version = "=1.2.1", features = ["std", "unstable"] } 11 | 12 | [patch.crates-io] 13 | sha2 = { git = "https://github.com/risc0/RustCrypto-hashes", tag = "sha2-v0.10.8-risczero.0" } 14 | ed25519-dalek = { git = "https://github.com/risc0/curve25519-dalek", tag = "curve25519-4.1.2-risczero.0" } 15 | tiny-keccak = { git = "https://github.com/risc0/tiny-keccak", tag = "tiny-keccak/v2.0.2-risczero.0" } 16 | k256 = { git = "https://github.com/risc0/RustCrypto-elliptic-curves", tag = "k256/v0.13.4-risczero.1" } 17 | p256 = { git = "https://github.com/risc0/RustCrypto-elliptic-curves", tag = "p256/v0.13.2-risczero.0" } 18 | rsa = { git = "https://github.com/risc0/RustCrypto-RSA", tag = "v0.9.6-risczero.0" } 19 | crypto-bigint = { git = "https://github.com/risc0/RustCrypto-crypto-bigint", tag = "v0.5.5-risczero.0" } 20 | 21 | [profile.release] 22 | # Empirically observed to result in the best performance for this binary (in particular, better than 23 | # "fat"). It's often a good idea to experiment with different optimization levels and options. 24 | lto = "thin" 25 | 26 | [features] 27 | risc0 = [] 28 | sp1 = [] 29 | -------------------------------------------------------------------------------- /programs/ecdsa-verify-risc0/src/main.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 RISC Zero, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #![no_main] 16 | 17 | use k256::{ 18 | ecdsa::{signature::Verifier, Signature, VerifyingKey}, 19 | EncodedPoint, 20 | }; 21 | use risc0_zkvm::guest::env; 22 | 23 | risc0_zkvm::guest::entry!(main); 24 | 25 | fn main() { 26 | // Decode the verifying key, message, and signature from the inputs. 27 | let (encoded_verifying_key, message, signature): (EncodedPoint, Vec, Signature) = 28 | env::read(); 29 | 30 | let verifying_key = VerifyingKey::from_encoded_point(&encoded_verifying_key).unwrap(); 31 | 32 | // Verify the signature, panicking if verification fails. 33 | verifying_key 34 | .verify(&message, &signature) 35 | .expect("ECDSA signature verification failed"); 36 | 37 | // Commit to the journal the verifying key and message that was signed. 38 | env::commit(&(encoded_verifying_key, message)); 39 | } 40 | -------------------------------------------------------------------------------- /programs/ecdsa-verify-sp1/.gitignore: -------------------------------------------------------------------------------- 1 | Cargo.lock 2 | -------------------------------------------------------------------------------- /programs/ecdsa-verify-sp1/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | [package] 3 | name = "ecdsa-verify-sp1" 4 | version = "0.1.0" 5 | edition = "2021" 6 | 7 | [dependencies] 8 | k256 = { version = "=0.13.3", features = ["serde", "ecdsa"] } 9 | sp1-zkvm = "3.3.0" 10 | 11 | [patch.crates-io] 12 | ecdsa-core = { git = "https://github.com/sp1-patches/signatures", package = "ecdsa", tag = "ecdsa-v0.16.9-patch-v3.3.0" } 13 | 14 | [features] 15 | risc0 = [] 16 | sp1 = [] 17 | -------------------------------------------------------------------------------- /programs/ecdsa-verify-sp1/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | 3 | use k256::{ 4 | ecdsa::{signature::Verifier, Signature, VerifyingKey}, 5 | EncodedPoint, 6 | }; 7 | 8 | sp1_zkvm::entrypoint!(main); 9 | 10 | fn main() { 11 | let (encoded_verifying_key, message, signature): (EncodedPoint, Vec, Signature) = sp1_zkvm::io::read(); 12 | 13 | let verifying_key = VerifyingKey::from_encoded_point(&encoded_verifying_key).unwrap(); 14 | 15 | verifying_key 16 | .verify(&message, &signature) 17 | .expect("ECDSA signature verification failed"); 18 | 19 | sp1_zkvm::io::commit(&(encoded_verifying_key, message)); 20 | } 21 | -------------------------------------------------------------------------------- /programs/eddsa-verify-risc0/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | [package] 3 | name = "eddsa-verify-risc0" 4 | version = "0.1.0" 5 | edition = "2021" 6 | 7 | [dependencies] 8 | ed25519-dalek = { version = "2.1.1", features = ["serde", "signature"] } 9 | risc0-zkvm = { version = "=1.2.1", features = ["std", "unstable"] } 10 | 11 | [patch.crates-io] 12 | sha2 = { git = "https://github.com/risc0/RustCrypto-hashes", tag = "sha2-v0.10.8-risczero.0" } 13 | ed25519-dalek = { git = "https://github.com/risc0/curve25519-dalek", tag = "curve25519-4.1.2-risczero.0" } 14 | tiny-keccak = { git = "https://github.com/risc0/tiny-keccak", tag = "tiny-keccak/v2.0.2-risczero.0" } 15 | k256 = { git = "https://github.com/risc0/RustCrypto-elliptic-curves", tag = "k256/v0.13.4-risczero.1" } 16 | p256 = { git = "https://github.com/risc0/RustCrypto-elliptic-curves", tag = "p256/v0.13.2-risczero.0" } 17 | rsa = { git = "https://github.com/risc0/RustCrypto-RSA", tag = "v0.9.6-risczero.0" } 18 | crypto-bigint = { git = "https://github.com/risc0/RustCrypto-crypto-bigint", tag = "v0.5.5-risczero.0" } 19 | 20 | [features] 21 | risc0 = [] 22 | sp1 = [] 23 | -------------------------------------------------------------------------------- /programs/eddsa-verify-risc0/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | risc0_zkvm::guest::entry!(main); 3 | 4 | use ed25519_dalek::{Signature, Verifier, VerifyingKey}; 5 | use risc0_zkvm::guest::env; 6 | 7 | fn main() { 8 | let times: u8 = env::read(); 9 | 10 | for _ in 0..times { 11 | verify_inner(); 12 | } 13 | } 14 | 15 | fn verify_inner() { 16 | let (signer, message, signature): (VerifyingKey, Vec, Signature) = env::read(); 17 | 18 | signer.verify(&message, &signature).expect("Ed25519 signature verification failed"); 19 | 20 | env::commit(&(signer, message)); 21 | } -------------------------------------------------------------------------------- /programs/eddsa-verify-sp1/.gitignore: -------------------------------------------------------------------------------- 1 | Cargo.lock 2 | -------------------------------------------------------------------------------- /programs/eddsa-verify-sp1/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | [package] 3 | name = "eddsa-verify-sp1" 4 | version = "0.1.0" 5 | edition = "2021" 6 | 7 | [dependencies] 8 | ed25519-dalek = { version = "2.1.1", features = ["serde", "signature"] } 9 | sp1-zkvm = "4.0.0-rc.10" 10 | 11 | [patch.crates-io] 12 | curve25519-dalek = { git = "https://github.com/sp1-patches/curve25519-dalek", tag = "patch-4.1.3-sp1-4.0.0-rc.3" } 13 | 14 | [features] 15 | risc0 = [] 16 | sp1 = [] 17 | -------------------------------------------------------------------------------- /programs/eddsa-verify-sp1/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | sp1_zkvm::entrypoint!(main); 3 | 4 | use ed25519_dalek::{Signature, Verifier, VerifyingKey}; 5 | 6 | fn main() { 7 | let times: u8 = sp1_zkvm::io::read(); 8 | for _ in 0..times { 9 | verify_inner(); 10 | } 11 | } 12 | 13 | fn verify_inner() { 14 | let (signer, message, signature): (VerifyingKey, Vec, Signature) = sp1_zkvm::io::read(); 15 | 16 | signer.verify(&message, &signature).expect("Ed25519 signature verification failed"); 17 | 18 | sp1_zkvm::io::commit(&(signer, message)); 19 | } -------------------------------------------------------------------------------- /programs/fibonacci/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | [package] 3 | name = "fibonacci" 4 | version = "0.1.0" 5 | edition = "2021" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | sp1-zkvm = "4.0.0-rc.10" 11 | risc0-zkvm = { version = "=1.2.1", default-features = false, features = ["std", "unstable"] } 12 | serde = { version = "1.0.204", default-features = false, features = ["derive"] } 13 | 14 | [features] 15 | risc0 = [] 16 | sp1 = [] 17 | -------------------------------------------------------------------------------- /programs/fibonacci/elf/riscv32im-succinct-zkvm-elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/succinctlabs/zkvm-perf/861cc5c18e3e31ae080640877642ce818e7eaff4/programs/fibonacci/elf/riscv32im-succinct-zkvm-elf -------------------------------------------------------------------------------- /programs/fibonacci/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | 3 | use std::hint::black_box; 4 | 5 | #[cfg(feature = "risc0")] 6 | risc0_zkvm::guest::entry!(main); 7 | 8 | #[cfg(feature = "sp1")] 9 | sp1_zkvm::entrypoint!(main); 10 | 11 | fn fibonacci(n: u32) -> u32 { 12 | let mut a = 0; 13 | let mut b = 1; 14 | for _ in 0..n { 15 | let sum = (a + b) % 7919; // Mod to avoid overflow 16 | a = b; 17 | b = sum; 18 | } 19 | b 20 | } 21 | 22 | pub fn main() { 23 | #[cfg(feature = "risc0")] 24 | let n: u32 = risc0_zkvm::guest::env::read(); 25 | #[cfg(feature = "sp1")] 26 | let n: u32 = sp1_zkvm::io::read(); 27 | let result = black_box(fibonacci(black_box(n))); 28 | println!("result: {}", result); 29 | } 30 | -------------------------------------------------------------------------------- /programs/groth-risc0/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | [package] 3 | name = "groth-risc0" 4 | version = "0.1.0" 5 | edition = "2021" 6 | 7 | [dependencies] 8 | risc0-zkvm = { version = "=1.2.1", default-features = false, features = ["std", "unstable"] } 9 | risc0-groth16 = { version = "=1.2.1" } 10 | serde_json = "1.0.133" 11 | 12 | [features] 13 | risc0 = [] 14 | sp1 = [] 15 | 16 | [patch.crates-io] 17 | kzg-rs = { git = "https://github.com/succinctlabs/kzg-rs.git", branch = "john/target-vendor" } 18 | sp1_bls12_381 = { git = "https://github.com/sp1-patches/bls12_381.git", package = "bls12_381", rev = "7e1b79041253d6f7b591534613245b3f60e05d8b", version = "0.8.0" } 19 | 20 | c-kzg = { git = "https://github.com/risc0/c-kzg-4844.git", branch = "p1.0.3" } 21 | sha2 = { git = "https://github.com/risc0/RustCrypto-hashes", tag = "sha2-v0.10.8-risczero.0" } 22 | ed25519-dalek = { git = "https://github.com/risc0/curve25519-dalek", tag = "curve25519-4.1.2-risczero.0" } 23 | tiny-keccak = { git = "https://github.com/risc0/tiny-keccak", tag = "tiny-keccak/v2.0.2-risczero.0" } 24 | k256 = { git = "https://github.com/risc0/RustCrypto-elliptic-curves", tag = "k256/v0.13.4-risczero.1" } 25 | p256 = { git = "https://github.com/risc0/RustCrypto-elliptic-curves", tag = "p256/v0.13.2-risczero.0" } 26 | rsa = { git = "https://github.com/risc0/RustCrypto-RSA", tag = "v0.9.6-risczero.0" } 27 | crypto-bigint = { git = "https://github.com/risc0/RustCrypto-crypto-bigint", tag = "v0.5.5-risczero.0" } -------------------------------------------------------------------------------- /programs/groth-risc0/src/main.rs: -------------------------------------------------------------------------------- 1 | 2 | #![no_main] 3 | risc0_zkvm::guest::entry!(main); 4 | 5 | use risc0_groth16::{Fr, Seal, Verifier, VerifyingKey}; 6 | use risc0_zkvm::{guest::env, sha::Digestible}; 7 | 8 | pub fn main() { 9 | let (seal, public_inputs, verifying_key): (Seal, Vec, VerifyingKey) = env::read(); 10 | 11 | Verifier::new(&seal, &public_inputs, &verifying_key) 12 | .unwrap() 13 | .verify() 14 | .unwrap(); 15 | 16 | env::commit(&(verifying_key.digest(), public_inputs.digest())); 17 | } 18 | -------------------------------------------------------------------------------- /programs/groth-sp1/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | [package] 3 | name = "groth-sp1" 4 | version = "0.1.0" 5 | edition = "2021" 6 | 7 | [dependencies] 8 | sp1-zkvm = "4.0.0-rc.10" 9 | sp1-verifier = "4.0.0-rc.10" 10 | 11 | [features] 12 | risc0 = [] 13 | sp1 = [] 14 | 15 | [patch.crates-io] 16 | substrate-bn-succinct = { git = "https://github.com/sp1-patches/bn", branch = "n/release-succinct" } -------------------------------------------------------------------------------- /programs/groth-sp1/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | sp1_zkvm::entrypoint!(main); 3 | 4 | use sp1_verifier::Groth16Verifier; 5 | 6 | fn main() { 7 | // Read the proof, public values, and vkey hash from the input stream. 8 | let proof = sp1_zkvm::io::read_vec(); 9 | let sp1_public_values = sp1_zkvm::io::read_vec(); 10 | let sp1_vkey_hash: String = sp1_zkvm::io::read(); 11 | 12 | // Verify the groth16 proof. 13 | let groth16_vk = *sp1_verifier::GROTH16_VK_BYTES; 14 | let result = Groth16Verifier::verify(&proof, &sp1_public_values, &sp1_vkey_hash, groth16_vk).unwrap(); 15 | } 16 | -------------------------------------------------------------------------------- /programs/helios-risc0/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | [package] 3 | name = "helios-risc0" 4 | version = "0.1.0" 5 | edition = "2021" 6 | 7 | [dependencies] 8 | # helios 9 | helios-consensus-core = { git = "https://github.com/a16z/helios", version = "0.7.0" } 10 | 11 | serde_cbor = "0.11.2" 12 | ssz-rs = { package = "ssz_rs", version = "0.9.0" } 13 | alloy-primitives = "0.7.7" 14 | tree_hash = "0.7.0" 15 | serde = "1.0.203" 16 | risc0-zkvm = { version = "=1.2.1", default-features = false, features = ["std", "unstable"] } 17 | 18 | [patch.crates-io] 19 | sha2 = { git = "https://github.com/risc0/RustCrypto-hashes", tag = "sha2-v0.10.8-risczero.0" } 20 | ed25519-dalek = { git = "https://github.com/risc0/curve25519-dalek", tag = "curve25519-4.1.2-risczero.0" } 21 | tiny-keccak = { git = "https://github.com/risc0/tiny-keccak", tag = "tiny-keccak/v2.0.2-risczero.0" } 22 | k256 = { git = "https://github.com/risc0/RustCrypto-elliptic-curves", tag = "k256/v0.13.4-risczero.1" } 23 | p256 = { git = "https://github.com/risc0/RustCrypto-elliptic-curves", tag = "p256/v0.13.2-risczero.0" } 24 | rsa = { git = "https://github.com/risc0/RustCrypto-RSA", tag = "v0.9.6-risczero.0" } 25 | crypto-bigint = { git = "https://github.com/risc0/RustCrypto-crypto-bigint", tag = "v0.5.5-risczero.0" } 26 | 27 | ethereum_hashing = { git = "https://github.com/ncitron/ethereum_hashing", rev = "7ee70944ed4fabe301551da8c447e4f4ae5e6c35" } 28 | 29 | [features] 30 | risc0 = [] 31 | sp1 = [] 32 | -------------------------------------------------------------------------------- /programs/helios-risc0/src/main.rs: -------------------------------------------------------------------------------- 1 | 2 | #![no_main] 3 | risc0_zkvm::guest::entry!(main); 4 | 5 | use helios_consensus_core::consensus_spec::MainnetConsensusSpec; 6 | use helios_consensus_core::types::Forks; 7 | use helios_consensus_core::types::{FinalityUpdate, LightClientStore, Update}; 8 | 9 | use alloy_primitives::B256; 10 | use helios_consensus_core::{ 11 | apply_finality_update, apply_update, verify_finality_update, verify_update, 12 | }; 13 | use ssz_rs::prelude::*; 14 | use tree_hash::TreeHash; 15 | 16 | #[derive(serde::Deserialize, Debug)] 17 | pub struct ProofInputs { 18 | pub sync_committee_updates: Vec>, 19 | pub finality_update: FinalityUpdate, 20 | pub expected_current_slot: u64, 21 | pub store: LightClientStore, 22 | pub genesis_root: B256, 23 | pub forks: Forks, 24 | } 25 | 26 | fn main() { 27 | let encoded_inputs: Vec = risc0_zkvm::guest::env::read(); 28 | 29 | let ProofInputs { 30 | sync_committee_updates, 31 | finality_update, 32 | expected_current_slot, 33 | mut store, 34 | genesis_root, 35 | forks, 36 | } = serde_cbor::from_slice(&encoded_inputs).unwrap(); 37 | 38 | let _prev_header: B256 = store.finalized_header.beacon().tree_hash_root(); 39 | let _prev_head = store.finalized_header.beacon().slot; 40 | 41 | // 1. Apply sync committee updates, if any 42 | for (index, update) in sync_committee_updates.iter().enumerate() { 43 | println!( 44 | "Processing update {} of {}.", 45 | index + 1, 46 | sync_committee_updates.len() 47 | ); 48 | let update_is_valid = 49 | verify_update(update, expected_current_slot, &store, genesis_root, &forks).is_ok(); 50 | 51 | if !update_is_valid { 52 | panic!("Update {} is invalid!", index + 1); 53 | } 54 | println!("Update {} is valid.", index + 1); 55 | apply_update(&mut store, update); 56 | } 57 | 58 | // 2. Apply finality update 59 | let finality_update_is_valid = verify_finality_update( 60 | &finality_update, 61 | expected_current_slot, 62 | &store, 63 | genesis_root, 64 | &forks, 65 | ) 66 | .is_ok(); 67 | if !finality_update_is_valid { 68 | panic!("Finality update is invalid!"); 69 | } 70 | println!("Finality update is valid."); 71 | 72 | apply_finality_update(&mut store, &finality_update); 73 | 74 | // 3. Commit new state root, header, and sync committee for usage in the on-chain contract 75 | let _header: B256 = store.finalized_header.beacon().tree_hash_root(); 76 | let _sync_committee_hash: B256 = store.current_sync_committee.tree_hash_root(); 77 | let _next_sync_committee_hash: B256 = match &mut store.next_sync_committee { 78 | Some(next_sync_committee) => next_sync_committee.tree_hash_root(), 79 | None => B256::ZERO, 80 | }; 81 | let _head = store.finalized_header.beacon().slot; 82 | 83 | // Commit here 84 | } 85 | -------------------------------------------------------------------------------- /programs/helios-sp1/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | [package] 3 | name = "helios-sp1" 4 | version = "0.1.0" 5 | edition = "2021" 6 | 7 | [dependencies] 8 | # helios 9 | helios-consensus-core = { git = "https://github.com/a16z/helios", version = "0.7.0" } 10 | serde_cbor = "0.11.2" 11 | ssz-rs = { package = "ssz_rs", version = "0.9.0" } 12 | alloy-primitives = "0.7.7" 13 | sp1-zkvm = "4.0.0-rc.10" 14 | tree_hash = "0.7.0" 15 | serde = "1.0.203" 16 | 17 | [patch.crates-io] 18 | sha2-0-9-9 = { git = "https://github.com/sp1-patches/RustCrypto-hashes", package = "sha2", tag = "patch-sha2-0.10.8-sp1-4.0.0-rc.3" } 19 | sha2 = { git = "https://github.com/sp1-patches/RustCrypto-hashes", package = "sha2", tag = "patch-sha2-0.9.9-sp1-4.0.0-rc.3" } 20 | tiny-keccak = { git = "https://github.com/sp1-patches/tiny-keccak", tag = "patch-2.0.2-sp1-4.0.0-rc.3" } 21 | # From upstream: https://github.com/a16z/helios/blob/master/Cargo.toml#L116C29-L116C72 22 | ethereum_hashing = { git = "https://github.com/ncitron/ethereum_hashing", rev = "7ee70944ed4fabe301551da8c447e4f4ae5e6c35" } 23 | bls12_381 = { git = "https://github.com/sp1-patches/bls12_381", branch = "n/prep-4.0.0" } 24 | 25 | [features] 26 | risc0 = [] 27 | sp1 = [] 28 | -------------------------------------------------------------------------------- /programs/helios-sp1/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | sp1_zkvm::entrypoint!(main); 3 | 4 | use helios_consensus_core::consensus_spec::MainnetConsensusSpec; 5 | use helios_consensus_core::types::Forks; 6 | use helios_consensus_core::types::{FinalityUpdate, LightClientStore, Update}; 7 | 8 | use alloy_primitives::B256; 9 | use helios_consensus_core::{ 10 | apply_finality_update, apply_update, verify_finality_update, verify_update, 11 | }; 12 | use ssz_rs::prelude::*; 13 | use tree_hash::TreeHash; 14 | 15 | #[derive(serde::Deserialize, Debug)] 16 | pub struct ProofInputs { 17 | pub sync_committee_updates: Vec>, 18 | pub finality_update: FinalityUpdate, 19 | pub expected_current_slot: u64, 20 | pub store: LightClientStore, 21 | pub genesis_root: B256, 22 | pub forks: Forks, 23 | } 24 | 25 | fn main() { 26 | let encoded_inputs = sp1_zkvm::io::read_vec(); 27 | 28 | let ProofInputs { 29 | sync_committee_updates, 30 | finality_update, 31 | expected_current_slot, 32 | mut store, 33 | genesis_root, 34 | forks, 35 | } = serde_cbor::from_slice(&encoded_inputs).unwrap(); 36 | 37 | let _prev_header: B256 = store.finalized_header.beacon().tree_hash_root(); 38 | let _prev_head = store.finalized_header.beacon().slot; 39 | 40 | // 1. Apply sync committee updates, if any 41 | for (index, update) in sync_committee_updates.iter().enumerate() { 42 | println!( 43 | "Processing update {} of {}.", 44 | index + 1, 45 | sync_committee_updates.len() 46 | ); 47 | let update_is_valid = 48 | verify_update(update, expected_current_slot, &store, genesis_root, &forks).is_ok(); 49 | 50 | if !update_is_valid { 51 | panic!("Update {} is invalid!", index + 1); 52 | } 53 | println!("Update {} is valid.", index + 1); 54 | apply_update(&mut store, update); 55 | } 56 | 57 | // 2. Apply finality update 58 | let finality_update_is_valid = verify_finality_update( 59 | &finality_update, 60 | expected_current_slot, 61 | &store, 62 | genesis_root, 63 | &forks, 64 | ) 65 | .is_ok(); 66 | if !finality_update_is_valid { 67 | panic!("Finality update is invalid!"); 68 | } 69 | println!("Finality update is valid."); 70 | 71 | apply_finality_update(&mut store, &finality_update); 72 | 73 | // 3. Commit new state root, header, and sync committee for usage in the on-chain contract 74 | let _header: B256 = store.finalized_header.beacon().tree_hash_root(); 75 | let _sync_committee_hash: B256 = store.current_sync_committee.tree_hash_root(); 76 | let _next_sync_committee_hash: B256 = match &mut store.next_sync_committee { 77 | Some(next_sync_committee) => next_sync_committee.tree_hash_root(), 78 | None => B256::ZERO, 79 | }; 80 | let _head = store.finalized_header.beacon().slot; 81 | 82 | // Commit here 83 | } 84 | -------------------------------------------------------------------------------- /programs/keccak256-risc0/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | [package] 3 | name = "keccak256-risc0" 4 | version = "0.1.0" 5 | edition = "2021" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | risc0-zkvm = { version = "=1.2.1", default-features = false, features = ["std", "unstable"] } 11 | serde = { version = "1.0.204", default-features = false, features = ["derive"] } 12 | sha3 = { version = "0.10", default-features = false } 13 | 14 | [features] 15 | risc0 = [] 16 | sp1 = [] 17 | 18 | [patch.crates-io] 19 | sha2 = { git = "https://github.com/risc0/RustCrypto-hashes", tag = "sha2-v0.10.8-risczero.0" } 20 | ed25519-dalek = { git = "https://github.com/risc0/curve25519-dalek", tag = "curve25519-4.1.2-risczero.0" } 21 | tiny-keccak = { git = "https://github.com/risc0/tiny-keccak", tag = "tiny-keccak/v2.0.2-risczero.0" } 22 | k256 = { git = "https://github.com/risc0/RustCrypto-elliptic-curves", tag = "k256/v0.13.4-risczero.1" } 23 | p256 = { git = "https://github.com/risc0/RustCrypto-elliptic-curves", tag = "p256/v0.13.2-risczero.0" } 24 | rsa = { git = "https://github.com/risc0/RustCrypto-RSA", tag = "v0.9.6-risczero.0" } 25 | crypto-bigint = { git = "https://github.com/risc0/RustCrypto-crypto-bigint", tag = "v0.5.5-risczero.0" } -------------------------------------------------------------------------------- /programs/keccak256-risc0/elf/riscv32im-succinct-zkvm-elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/succinctlabs/zkvm-perf/861cc5c18e3e31ae080640877642ce818e7eaff4/programs/keccak256-risc0/elf/riscv32im-succinct-zkvm-elf -------------------------------------------------------------------------------- /programs/keccak256-risc0/src/main.rs: -------------------------------------------------------------------------------- 1 | // This code is borrowed from RISC Zero's benchmarks. 2 | // 3 | // Copyright 2024 RISC Zero, Inc. 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | #![no_main] 18 | 19 | use risc0_zkvm::{guest::env, sha, sha::Sha256}; 20 | use sha3::{Digest as _, Keccak256}; 21 | 22 | risc0_zkvm::guest::entry!(main); 23 | 24 | fn main() { 25 | let data: Vec = env::read(); 26 | let hash = keccak(&data); 27 | env::commit(&hash) 28 | } 29 | 30 | #[inline] 31 | pub fn keccak(data: impl AsRef<[u8]>) -> [u8; 32] { 32 | Keccak256::digest(data).into() 33 | } -------------------------------------------------------------------------------- /programs/keccak256-sp1/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "autocfg" 7 | version = "1.3.0" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" 10 | 11 | [[package]] 12 | name = "bincode" 13 | version = "1.3.3" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" 16 | dependencies = [ 17 | "serde", 18 | ] 19 | 20 | [[package]] 21 | name = "block-buffer" 22 | version = "0.10.4" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" 25 | dependencies = [ 26 | "generic-array", 27 | ] 28 | 29 | [[package]] 30 | name = "byteorder" 31 | version = "1.5.0" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" 34 | 35 | [[package]] 36 | name = "cfg-if" 37 | version = "1.0.0" 38 | source = "registry+https://github.com/rust-lang/crates.io-index" 39 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 40 | 41 | [[package]] 42 | name = "cpufeatures" 43 | version = "0.2.12" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" 46 | dependencies = [ 47 | "libc", 48 | ] 49 | 50 | [[package]] 51 | name = "crypto-common" 52 | version = "0.1.6" 53 | source = "registry+https://github.com/rust-lang/crates.io-index" 54 | checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" 55 | dependencies = [ 56 | "generic-array", 57 | "typenum", 58 | ] 59 | 60 | [[package]] 61 | name = "digest" 62 | version = "0.10.7" 63 | source = "registry+https://github.com/rust-lang/crates.io-index" 64 | checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" 65 | dependencies = [ 66 | "block-buffer", 67 | "crypto-common", 68 | ] 69 | 70 | [[package]] 71 | name = "either" 72 | version = "1.13.0" 73 | source = "registry+https://github.com/rust-lang/crates.io-index" 74 | checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" 75 | 76 | [[package]] 77 | name = "gcd" 78 | version = "2.3.0" 79 | source = "registry+https://github.com/rust-lang/crates.io-index" 80 | checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a" 81 | 82 | [[package]] 83 | name = "generic-array" 84 | version = "0.14.7" 85 | source = "registry+https://github.com/rust-lang/crates.io-index" 86 | checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" 87 | dependencies = [ 88 | "typenum", 89 | "version_check", 90 | ] 91 | 92 | [[package]] 93 | name = "getrandom" 94 | version = "0.2.15" 95 | source = "registry+https://github.com/rust-lang/crates.io-index" 96 | checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" 97 | dependencies = [ 98 | "cfg-if", 99 | "libc", 100 | "wasi", 101 | ] 102 | 103 | [[package]] 104 | name = "hex" 105 | version = "0.4.3" 106 | source = "registry+https://github.com/rust-lang/crates.io-index" 107 | checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" 108 | 109 | [[package]] 110 | name = "itertools" 111 | version = "0.12.1" 112 | source = "registry+https://github.com/rust-lang/crates.io-index" 113 | checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" 114 | dependencies = [ 115 | "either", 116 | ] 117 | 118 | [[package]] 119 | name = "keccak" 120 | version = "0.1.5" 121 | source = "registry+https://github.com/rust-lang/crates.io-index" 122 | checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" 123 | dependencies = [ 124 | "cpufeatures", 125 | ] 126 | 127 | [[package]] 128 | name = "keccak256-sp1" 129 | version = "0.1.0" 130 | dependencies = [ 131 | "serde", 132 | "sha3", 133 | "sp1-zkvm", 134 | ] 135 | 136 | [[package]] 137 | name = "lazy_static" 138 | version = "1.5.0" 139 | source = "registry+https://github.com/rust-lang/crates.io-index" 140 | checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" 141 | 142 | [[package]] 143 | name = "libc" 144 | version = "0.2.155" 145 | source = "registry+https://github.com/rust-lang/crates.io-index" 146 | checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" 147 | 148 | [[package]] 149 | name = "libm" 150 | version = "0.2.8" 151 | source = "registry+https://github.com/rust-lang/crates.io-index" 152 | checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" 153 | 154 | [[package]] 155 | name = "num-bigint" 156 | version = "0.4.6" 157 | source = "registry+https://github.com/rust-lang/crates.io-index" 158 | checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" 159 | dependencies = [ 160 | "num-integer", 161 | "num-traits", 162 | ] 163 | 164 | [[package]] 165 | name = "num-integer" 166 | version = "0.1.46" 167 | source = "registry+https://github.com/rust-lang/crates.io-index" 168 | checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" 169 | dependencies = [ 170 | "num-traits", 171 | ] 172 | 173 | [[package]] 174 | name = "num-traits" 175 | version = "0.2.19" 176 | source = "registry+https://github.com/rust-lang/crates.io-index" 177 | checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" 178 | dependencies = [ 179 | "autocfg", 180 | ] 181 | 182 | [[package]] 183 | name = "once_cell" 184 | version = "1.19.0" 185 | source = "registry+https://github.com/rust-lang/crates.io-index" 186 | checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" 187 | 188 | [[package]] 189 | name = "p3-baby-bear" 190 | version = "0.2.0-succinct" 191 | source = "registry+https://github.com/rust-lang/crates.io-index" 192 | checksum = "080896e9d09e9761982febafe3b3da5cbf320e32f0c89b6e2e01e875129f4c2d" 193 | dependencies = [ 194 | "num-bigint", 195 | "p3-field", 196 | "p3-mds", 197 | "p3-poseidon2", 198 | "p3-symmetric", 199 | "rand", 200 | "serde", 201 | ] 202 | 203 | [[package]] 204 | name = "p3-dft" 205 | version = "0.2.0-succinct" 206 | source = "registry+https://github.com/rust-lang/crates.io-index" 207 | checksum = "292e97d02d4c38d8b306c2b8c0428bf15f4d32a11a40bcf80018f675bf33267e" 208 | dependencies = [ 209 | "p3-field", 210 | "p3-matrix", 211 | "p3-maybe-rayon", 212 | "p3-util", 213 | "tracing", 214 | ] 215 | 216 | [[package]] 217 | name = "p3-field" 218 | version = "0.2.0-succinct" 219 | source = "registry+https://github.com/rust-lang/crates.io-index" 220 | checksum = "f91d8e5f9ede1171adafdb0b6a0df1827fbd4eb6a6217bfa36374e5d86248757" 221 | dependencies = [ 222 | "itertools", 223 | "num-bigint", 224 | "num-traits", 225 | "p3-util", 226 | "rand", 227 | "serde", 228 | ] 229 | 230 | [[package]] 231 | name = "p3-matrix" 232 | version = "0.2.0-succinct" 233 | source = "registry+https://github.com/rust-lang/crates.io-index" 234 | checksum = "98bf2c7680b8e906a5e147fe4ceb05a11cc9fa35678aa724333bcb35c72483c1" 235 | dependencies = [ 236 | "itertools", 237 | "p3-field", 238 | "p3-maybe-rayon", 239 | "p3-util", 240 | "rand", 241 | "serde", 242 | "tracing", 243 | ] 244 | 245 | [[package]] 246 | name = "p3-maybe-rayon" 247 | version = "0.2.0" 248 | source = "registry+https://github.com/rust-lang/crates.io-index" 249 | checksum = "3925562a4c03183eafc92fd07b19f65ac6cb4b48d68c3920ce58d9bee6efe362" 250 | 251 | [[package]] 252 | name = "p3-mds" 253 | version = "0.2.0-succinct" 254 | source = "registry+https://github.com/rust-lang/crates.io-index" 255 | checksum = "706cea48976f54702dc68dffa512684c1304d1a3606cadea423cfe0b1ee25134" 256 | dependencies = [ 257 | "itertools", 258 | "p3-dft", 259 | "p3-field", 260 | "p3-matrix", 261 | "p3-symmetric", 262 | "p3-util", 263 | "rand", 264 | ] 265 | 266 | [[package]] 267 | name = "p3-poseidon2" 268 | version = "0.2.0-succinct" 269 | source = "registry+https://github.com/rust-lang/crates.io-index" 270 | checksum = "a2ce5f5ec7f1ba3a233a671621029def7bd416e7c51218c9d1167d21602cf312" 271 | dependencies = [ 272 | "gcd", 273 | "p3-field", 274 | "p3-mds", 275 | "p3-symmetric", 276 | "rand", 277 | "serde", 278 | ] 279 | 280 | [[package]] 281 | name = "p3-symmetric" 282 | version = "0.2.0-succinct" 283 | source = "registry+https://github.com/rust-lang/crates.io-index" 284 | checksum = "2f29dc5bb6c99d3de75869d5c086874b64890280eeb7d3e068955f939e219253" 285 | dependencies = [ 286 | "itertools", 287 | "p3-field", 288 | "serde", 289 | ] 290 | 291 | [[package]] 292 | name = "p3-util" 293 | version = "0.2.0" 294 | source = "registry+https://github.com/rust-lang/crates.io-index" 295 | checksum = "88dd5ca3eb6ff33cb20084778c32a6d68064a1913b4632437408c5a1098408b3" 296 | dependencies = [ 297 | "serde", 298 | ] 299 | 300 | [[package]] 301 | name = "pin-project-lite" 302 | version = "0.2.14" 303 | source = "registry+https://github.com/rust-lang/crates.io-index" 304 | checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" 305 | 306 | [[package]] 307 | name = "ppv-lite86" 308 | version = "0.2.20" 309 | source = "registry+https://github.com/rust-lang/crates.io-index" 310 | checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" 311 | dependencies = [ 312 | "zerocopy", 313 | ] 314 | 315 | [[package]] 316 | name = "proc-macro2" 317 | version = "1.0.92" 318 | source = "registry+https://github.com/rust-lang/crates.io-index" 319 | checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" 320 | dependencies = [ 321 | "unicode-ident", 322 | ] 323 | 324 | [[package]] 325 | name = "quote" 326 | version = "1.0.36" 327 | source = "registry+https://github.com/rust-lang/crates.io-index" 328 | checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" 329 | dependencies = [ 330 | "proc-macro2", 331 | ] 332 | 333 | [[package]] 334 | name = "rand" 335 | version = "0.8.5" 336 | source = "registry+https://github.com/rust-lang/crates.io-index" 337 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 338 | dependencies = [ 339 | "libc", 340 | "rand_chacha", 341 | "rand_core", 342 | ] 343 | 344 | [[package]] 345 | name = "rand_chacha" 346 | version = "0.3.1" 347 | source = "registry+https://github.com/rust-lang/crates.io-index" 348 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 349 | dependencies = [ 350 | "ppv-lite86", 351 | "rand_core", 352 | ] 353 | 354 | [[package]] 355 | name = "rand_core" 356 | version = "0.6.4" 357 | source = "registry+https://github.com/rust-lang/crates.io-index" 358 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 359 | dependencies = [ 360 | "getrandom", 361 | ] 362 | 363 | [[package]] 364 | name = "serde" 365 | version = "1.0.204" 366 | source = "registry+https://github.com/rust-lang/crates.io-index" 367 | checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" 368 | dependencies = [ 369 | "serde_derive", 370 | ] 371 | 372 | [[package]] 373 | name = "serde_derive" 374 | version = "1.0.204" 375 | source = "registry+https://github.com/rust-lang/crates.io-index" 376 | checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" 377 | dependencies = [ 378 | "proc-macro2", 379 | "quote", 380 | "syn", 381 | ] 382 | 383 | [[package]] 384 | name = "sha2" 385 | version = "0.10.8" 386 | source = "registry+https://github.com/rust-lang/crates.io-index" 387 | checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" 388 | dependencies = [ 389 | "cfg-if", 390 | "cpufeatures", 391 | "digest", 392 | ] 393 | 394 | [[package]] 395 | name = "sha3" 396 | version = "0.10.8" 397 | source = "git+https://github.com/sp1-patches/RustCrypto-hashes?tag=patch-sha3-0.10.8-sp1-4.0.0-rc.3#8f6d303c0861ba7e5adcc36207c0f41fe5edaabc" 398 | dependencies = [ 399 | "digest", 400 | "keccak", 401 | ] 402 | 403 | [[package]] 404 | name = "sp1-lib" 405 | version = "4.0.1" 406 | source = "registry+https://github.com/rust-lang/crates.io-index" 407 | checksum = "aac3d3deeed25e9cad80e4275faf5954aa63f213ed3422f0e098dd2d0c1b0c0e" 408 | dependencies = [ 409 | "bincode", 410 | "serde", 411 | "sp1-primitives", 412 | ] 413 | 414 | [[package]] 415 | name = "sp1-primitives" 416 | version = "4.0.1" 417 | source = "registry+https://github.com/rust-lang/crates.io-index" 418 | checksum = "09b25a09b455dfae9c688da05718b205e8bd4afab36cd912d54639f5d4035815" 419 | dependencies = [ 420 | "bincode", 421 | "hex", 422 | "lazy_static", 423 | "num-bigint", 424 | "p3-baby-bear", 425 | "p3-field", 426 | "p3-poseidon2", 427 | "p3-symmetric", 428 | "serde", 429 | "sha2", 430 | ] 431 | 432 | [[package]] 433 | name = "sp1-zkvm" 434 | version = "4.0.1" 435 | source = "registry+https://github.com/rust-lang/crates.io-index" 436 | checksum = "f971db10d58b13c9a5d8cee4f7d1195d6f8a2debb9c33bd67f4eea5817432d42" 437 | dependencies = [ 438 | "cfg-if", 439 | "getrandom", 440 | "lazy_static", 441 | "libm", 442 | "rand", 443 | "sha2", 444 | "sp1-lib", 445 | "sp1-primitives", 446 | ] 447 | 448 | [[package]] 449 | name = "syn" 450 | version = "2.0.90" 451 | source = "registry+https://github.com/rust-lang/crates.io-index" 452 | checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" 453 | dependencies = [ 454 | "proc-macro2", 455 | "quote", 456 | "unicode-ident", 457 | ] 458 | 459 | [[package]] 460 | name = "tracing" 461 | version = "0.1.40" 462 | source = "registry+https://github.com/rust-lang/crates.io-index" 463 | checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" 464 | dependencies = [ 465 | "pin-project-lite", 466 | "tracing-attributes", 467 | "tracing-core", 468 | ] 469 | 470 | [[package]] 471 | name = "tracing-attributes" 472 | version = "0.1.27" 473 | source = "registry+https://github.com/rust-lang/crates.io-index" 474 | checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" 475 | dependencies = [ 476 | "proc-macro2", 477 | "quote", 478 | "syn", 479 | ] 480 | 481 | [[package]] 482 | name = "tracing-core" 483 | version = "0.1.32" 484 | source = "registry+https://github.com/rust-lang/crates.io-index" 485 | checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" 486 | dependencies = [ 487 | "once_cell", 488 | ] 489 | 490 | [[package]] 491 | name = "typenum" 492 | version = "1.17.0" 493 | source = "registry+https://github.com/rust-lang/crates.io-index" 494 | checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" 495 | 496 | [[package]] 497 | name = "unicode-ident" 498 | version = "1.0.12" 499 | source = "registry+https://github.com/rust-lang/crates.io-index" 500 | checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" 501 | 502 | [[package]] 503 | name = "version_check" 504 | version = "0.9.5" 505 | source = "registry+https://github.com/rust-lang/crates.io-index" 506 | checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 507 | 508 | [[package]] 509 | name = "wasi" 510 | version = "0.11.0+wasi-snapshot-preview1" 511 | source = "registry+https://github.com/rust-lang/crates.io-index" 512 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 513 | 514 | [[package]] 515 | name = "zerocopy" 516 | version = "0.7.35" 517 | source = "registry+https://github.com/rust-lang/crates.io-index" 518 | checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" 519 | dependencies = [ 520 | "byteorder", 521 | "zerocopy-derive", 522 | ] 523 | 524 | [[package]] 525 | name = "zerocopy-derive" 526 | version = "0.7.35" 527 | source = "registry+https://github.com/rust-lang/crates.io-index" 528 | checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" 529 | dependencies = [ 530 | "proc-macro2", 531 | "quote", 532 | "syn", 533 | ] 534 | -------------------------------------------------------------------------------- /programs/keccak256-sp1/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | [package] 3 | name = "keccak256-sp1" 4 | version = "0.1.0" 5 | edition = "2021" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | sp1-zkvm = "4.0.0-rc.10" 11 | serde = { version = "1.0.204", default-features = false, features = ["derive"] } 12 | sha3 = { version = "0.10.8", default-features = false } 13 | 14 | [features] 15 | risc0 = [] 16 | sp1 = [] 17 | 18 | [patch.crates-io] 19 | sha3-v0-10-8 = { git = "https://github.com/sp1-patches/RustCrypto-hashes", package = "sha3", tag = "patch-sha3-0.10.8-sp1-4.0.0-rc.3" } 20 | -------------------------------------------------------------------------------- /programs/keccak256-sp1/elf/riscv32im-succinct-zkvm-elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/succinctlabs/zkvm-perf/861cc5c18e3e31ae080640877642ce818e7eaff4/programs/keccak256-sp1/elf/riscv32im-succinct-zkvm-elf -------------------------------------------------------------------------------- /programs/keccak256-sp1/src/main.rs: -------------------------------------------------------------------------------- 1 | // This code is borrowed from RISC Zero's benchmarks. 2 | // 3 | // Copyright 2024 RISC Zero, Inc. 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | #![no_main] 18 | 19 | use sha3::{Digest as _, Keccak256}; 20 | 21 | sp1_zkvm::entrypoint!(main); 22 | 23 | fn main() { 24 | let data: Vec = sp1_zkvm::io::read(); 25 | let hash = keccak(&data); 26 | sp1_zkvm::io::commit(&hash) 27 | } 28 | 29 | #[inline] 30 | pub fn keccak(data: impl AsRef<[u8]>) -> [u8; 32] { 31 | Keccak256::digest(data).into() 32 | } -------------------------------------------------------------------------------- /programs/loop/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | [package] 3 | name = "loop" 4 | version = "0.1.0" 5 | edition = "2021" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | sp1-zkvm = "4.0.0-rc.10" 11 | risc0-zkvm = { version = "=1.2.1", default-features = false, features = ["std", "unstable"] } 12 | serde = { version = "1.0.204", default-features = false, features = ["derive"] } 13 | 14 | [features] 15 | risc0 = [] 16 | sp1 = [] 17 | -------------------------------------------------------------------------------- /programs/loop/elf/riscv32im-succinct-zkvm-elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/succinctlabs/zkvm-perf/861cc5c18e3e31ae080640877642ce818e7eaff4/programs/loop/elf/riscv32im-succinct-zkvm-elf -------------------------------------------------------------------------------- /programs/loop/src/main.rs: -------------------------------------------------------------------------------- 1 | // This code is borrowed from RISC Zero's benchmarks. 2 | // 3 | // Copyright 2024 RISC Zero, Inc. 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | #![no_main] 18 | 19 | #[cfg(feature = "risc0")] 20 | risc0_zkvm::guest::entry!(main); 21 | 22 | #[cfg(feature = "sp1")] 23 | sp1_zkvm::entrypoint!(main); 24 | 25 | #[cfg(target_os = "zkvm")] 26 | use core::arch::asm; 27 | 28 | fn main() { 29 | #[cfg(feature = "sp1")] 30 | let iterations: usize = sp1_zkvm::io::read(); 31 | #[cfg(feature = "risc0")] 32 | let iterations: usize = risc0_zkvm::guest::env::read(); 33 | 34 | for i in 0..iterations { 35 | memory_barrier(&i); 36 | } 37 | } 38 | 39 | #[allow(unused_variables)] 40 | pub fn memory_barrier(ptr: *const T) { 41 | #[cfg(target_os = "zkvm")] 42 | unsafe { 43 | asm!("/* {0} */", in(reg) (ptr)) 44 | } 45 | #[cfg(not(target_os = "zkvm"))] 46 | core::sync::atomic::fence(core::sync::atomic::Ordering::SeqCst) 47 | } -------------------------------------------------------------------------------- /programs/rsp-risc0/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | [package] 3 | name = "rsp-risc0" 4 | version = "0.1.0" 5 | edition = "2021" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | risc0-zkvm = { version = "=1.2.1", default-features = false, features = ["std", "unstable"] } 11 | risc0-zkvm-platform = { version = "=1.2.1", default-features = false, features = ["sys-getenv"] } 12 | serde = { version = "1.0.204", default-features = false, features = ["derive"] } 13 | bincode = "1.3.3" 14 | rsp-client-executor = { git = "https://github.com/succinctlabs/rsp/", rev = "4ceefdfb74c1691dd009168f0c7aec3d746ef8b3" } 15 | c-kzg = { version = "=1.0.3", features = ["risc0-ffi"] } 16 | 17 | [features] 18 | risc0 = [] 19 | sp1 = [] 20 | 21 | [patch.crates-io] 22 | kzg-rs = { git = "https://github.com/succinctlabs/kzg-rs.git", branch = "john/target-vendor" } 23 | sp1_bls12_381 = { git = "https://github.com/sp1-patches/bls12_381.git", package = "bls12_381", rev = "7e1b79041253d6f7b591534613245b3f60e05d8b", version = "0.8.0" } 24 | 25 | c-kzg = { git = "https://github.com/risc0/c-kzg-4844.git", branch = "p1.0.3" } 26 | sha2 = { git = "https://github.com/risc0/RustCrypto-hashes", tag = "sha2-v0.10.8-risczero.0" } 27 | ed25519-dalek = { git = "https://github.com/risc0/curve25519-dalek", tag = "curve25519-4.1.2-risczero.0" } 28 | tiny-keccak = { git = "https://github.com/risc0/tiny-keccak", tag = "tiny-keccak/v2.0.2-risczero.0" } 29 | k256 = { git = "https://github.com/risc0/RustCrypto-elliptic-curves", tag = "k256/v0.13.4-risczero.1" } 30 | p256 = { git = "https://github.com/risc0/RustCrypto-elliptic-curves", tag = "p256/v0.13.2-risczero.0" } 31 | rsa = { git = "https://github.com/risc0/RustCrypto-RSA", tag = "v0.9.6-risczero.0" } 32 | crypto-bigint = { git = "https://github.com/risc0/RustCrypto-crypto-bigint", tag = "v0.5.5-risczero.0" } -------------------------------------------------------------------------------- /programs/rsp-risc0/elf/riscv32im-succinct-zkvm-elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/succinctlabs/zkvm-perf/861cc5c18e3e31ae080640877642ce818e7eaff4/programs/rsp-risc0/elf/riscv32im-succinct-zkvm-elf -------------------------------------------------------------------------------- /programs/rsp-risc0/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | 3 | use rsp_client_executor::{io::ClientExecutorInput, ClientExecutor, EthereumVariant}; 4 | 5 | risc0_zkvm::guest::entry!(main); 6 | 7 | pub fn main() { 8 | // Read the input. 9 | let input: Vec = risc0_zkvm::guest::env::read(); 10 | let input = bincode::deserialize::(&input).unwrap(); 11 | 12 | // Execute the block. 13 | let executor = ClientExecutor; 14 | let header = executor.execute::(input).expect("failed to execute client"); 15 | let block_hash = header.hash_slow(); 16 | println!("block_hash: {:?}", block_hash); 17 | } -------------------------------------------------------------------------------- /programs/rsp-sp1/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | [package] 3 | name = "rsp-sp1" 4 | version = "0.1.0" 5 | edition = "2021" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | sp1-zkvm = "4.0.0-rc.10" 11 | serde = { version = "1.0.204", default-features = false, features = ["derive"] } 12 | bincode = "1.3.3" 13 | rsp-client-executor = { git = "https://github.com/succinctlabs/rsp/", rev = "249b34ee0c5307b59dc48f1f45a474b04669c6c4" } 14 | 15 | [features] 16 | risc0 = [] 17 | sp1 = [] 18 | 19 | [patch.crates-io] 20 | sha2 = { git = "https://github.com/sp1-patches/RustCrypto-hashes", package = "sha2", tag = "patch-sha2-0.10.8-sp1-4.0.0-rc.3" } 21 | ecdsa-core = { git = "https://github.com/sp1-patches/signatures", package = "ecdsa", tag = "patch-0.16.9-sp1-4.0.0-rc.3-v2" } 22 | tiny-keccak = { git = "https://github.com/sp1-patches/tiny-keccak", tag = "patch-2.0.2-sp1-4.0.0-rc.3" } 23 | bn = { git = "https://github.com/sp1-patches/bn", tag = "patch-0.6.0-sp1-4.0.0-rc.3-v1", package = "substrate-bn" } 24 | kzg-rs = { git = "https://github.com/succinctlabs/kzg-rs", branch = "n/v4" } -------------------------------------------------------------------------------- /programs/rsp-sp1/elf/riscv32im-succinct-zkvm-elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/succinctlabs/zkvm-perf/861cc5c18e3e31ae080640877642ce818e7eaff4/programs/rsp-sp1/elf/riscv32im-succinct-zkvm-elf -------------------------------------------------------------------------------- /programs/rsp-sp1/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | 3 | use rsp_client_executor::{io::ClientExecutorInput, ClientExecutor, EthereumVariant}; 4 | 5 | sp1_zkvm::entrypoint!(main); 6 | 7 | pub fn main() { 8 | // Read the input. 9 | let input: Vec = sp1_zkvm::io::read_vec(); 10 | let input = bincode::deserialize::(&input).unwrap(); 11 | 12 | // Execute the block. 13 | let executor = ClientExecutor; 14 | let header = executor.execute::(input).expect("failed to execute client"); 15 | let block_hash = header.hash_slow(); 16 | 17 | println!("block_hash: {:?}", block_hash); 18 | } -------------------------------------------------------------------------------- /programs/sha256-risc0/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | [package] 3 | name = "sha256-risc0" 4 | version = "0.1.0" 5 | edition = "2021" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | risc0-zkvm = { version = "=1.2.1", default-features = false, features = ["std", "unstable"] } 11 | sha2 = { git = "https://github.com/risc0/RustCrypto-hashes", tag = "sha2-v0.10.8-risczero.0" } 12 | serde = { version = "1.0.204", default-features = false, features = ["derive"] } 13 | 14 | [patch.crates-io] 15 | sha2 = { git = "https://github.com/risc0/RustCrypto-hashes", tag = "sha2-v0.10.8-risczero.0" } 16 | ed25519-dalek = { git = "https://github.com/risc0/curve25519-dalek", tag = "curve25519-4.1.2-risczero.0" } 17 | tiny-keccak = { git = "https://github.com/risc0/tiny-keccak", tag = "tiny-keccak/v2.0.2-risczero.0" } 18 | k256 = { git = "https://github.com/risc0/RustCrypto-elliptic-curves", tag = "k256/v0.13.4-risczero.1" } 19 | p256 = { git = "https://github.com/risc0/RustCrypto-elliptic-curves", tag = "p256/v0.13.2-risczero.0" } 20 | rsa = { git = "https://github.com/risc0/RustCrypto-RSA", tag = "v0.9.6-risczero.0" } 21 | crypto-bigint = { git = "https://github.com/risc0/RustCrypto-crypto-bigint", tag = "v0.5.5-risczero.0" } 22 | 23 | [features] 24 | risc0 = [] 25 | sp1 = [] -------------------------------------------------------------------------------- /programs/sha256-risc0/elf/riscv32im-succinct-zkvm-elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/succinctlabs/zkvm-perf/861cc5c18e3e31ae080640877642ce818e7eaff4/programs/sha256-risc0/elf/riscv32im-succinct-zkvm-elf -------------------------------------------------------------------------------- /programs/sha256-risc0/src/main.rs: -------------------------------------------------------------------------------- 1 | // This code is borrowed from RISC Zero's benchmarks. 2 | // 3 | // Copyright 2024 RISC Zero, Inc. 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | #![no_main] 18 | 19 | use sha2::{Digest, Sha256}; 20 | use risc0_zkvm::{guest::env}; 21 | 22 | risc0_zkvm::guest::entry!(main); 23 | 24 | fn main() { 25 | let data: Vec = env::read(); 26 | let mut hasher = Sha256::new(); 27 | hasher.update(&data); 28 | let hash = hasher.finalize(); 29 | env::commit(&hash.to_vec()) 30 | } -------------------------------------------------------------------------------- /programs/sha256-sp1/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "autocfg" 7 | version = "1.4.0" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" 10 | 11 | [[package]] 12 | name = "bincode" 13 | version = "1.3.3" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" 16 | dependencies = [ 17 | "serde", 18 | ] 19 | 20 | [[package]] 21 | name = "block-buffer" 22 | version = "0.10.4" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" 25 | dependencies = [ 26 | "generic-array", 27 | ] 28 | 29 | [[package]] 30 | name = "byteorder" 31 | version = "1.5.0" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" 34 | 35 | [[package]] 36 | name = "cfg-if" 37 | version = "1.0.0" 38 | source = "registry+https://github.com/rust-lang/crates.io-index" 39 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 40 | 41 | [[package]] 42 | name = "cpufeatures" 43 | version = "0.2.16" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" 46 | dependencies = [ 47 | "libc", 48 | ] 49 | 50 | [[package]] 51 | name = "crypto-common" 52 | version = "0.1.6" 53 | source = "registry+https://github.com/rust-lang/crates.io-index" 54 | checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" 55 | dependencies = [ 56 | "generic-array", 57 | "typenum", 58 | ] 59 | 60 | [[package]] 61 | name = "digest" 62 | version = "0.10.7" 63 | source = "registry+https://github.com/rust-lang/crates.io-index" 64 | checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" 65 | dependencies = [ 66 | "block-buffer", 67 | "crypto-common", 68 | ] 69 | 70 | [[package]] 71 | name = "either" 72 | version = "1.13.0" 73 | source = "registry+https://github.com/rust-lang/crates.io-index" 74 | checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" 75 | 76 | [[package]] 77 | name = "gcd" 78 | version = "2.3.0" 79 | source = "registry+https://github.com/rust-lang/crates.io-index" 80 | checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a" 81 | 82 | [[package]] 83 | name = "generic-array" 84 | version = "0.14.7" 85 | source = "registry+https://github.com/rust-lang/crates.io-index" 86 | checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" 87 | dependencies = [ 88 | "typenum", 89 | "version_check", 90 | ] 91 | 92 | [[package]] 93 | name = "getrandom" 94 | version = "0.2.15" 95 | source = "registry+https://github.com/rust-lang/crates.io-index" 96 | checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" 97 | dependencies = [ 98 | "cfg-if", 99 | "libc", 100 | "wasi", 101 | ] 102 | 103 | [[package]] 104 | name = "hex" 105 | version = "0.4.3" 106 | source = "registry+https://github.com/rust-lang/crates.io-index" 107 | checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" 108 | 109 | [[package]] 110 | name = "itertools" 111 | version = "0.12.1" 112 | source = "registry+https://github.com/rust-lang/crates.io-index" 113 | checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" 114 | dependencies = [ 115 | "either", 116 | ] 117 | 118 | [[package]] 119 | name = "lazy_static" 120 | version = "1.5.0" 121 | source = "registry+https://github.com/rust-lang/crates.io-index" 122 | checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" 123 | 124 | [[package]] 125 | name = "libc" 126 | version = "0.2.169" 127 | source = "registry+https://github.com/rust-lang/crates.io-index" 128 | checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" 129 | 130 | [[package]] 131 | name = "libm" 132 | version = "0.2.11" 133 | source = "registry+https://github.com/rust-lang/crates.io-index" 134 | checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" 135 | 136 | [[package]] 137 | name = "num-bigint" 138 | version = "0.4.6" 139 | source = "registry+https://github.com/rust-lang/crates.io-index" 140 | checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" 141 | dependencies = [ 142 | "num-integer", 143 | "num-traits", 144 | ] 145 | 146 | [[package]] 147 | name = "num-integer" 148 | version = "0.1.46" 149 | source = "registry+https://github.com/rust-lang/crates.io-index" 150 | checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" 151 | dependencies = [ 152 | "num-traits", 153 | ] 154 | 155 | [[package]] 156 | name = "num-traits" 157 | version = "0.2.19" 158 | source = "registry+https://github.com/rust-lang/crates.io-index" 159 | checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" 160 | dependencies = [ 161 | "autocfg", 162 | ] 163 | 164 | [[package]] 165 | name = "once_cell" 166 | version = "1.20.2" 167 | source = "registry+https://github.com/rust-lang/crates.io-index" 168 | checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" 169 | 170 | [[package]] 171 | name = "p3-baby-bear" 172 | version = "0.2.0-succinct" 173 | source = "registry+https://github.com/rust-lang/crates.io-index" 174 | checksum = "080896e9d09e9761982febafe3b3da5cbf320e32f0c89b6e2e01e875129f4c2d" 175 | dependencies = [ 176 | "num-bigint", 177 | "p3-field", 178 | "p3-mds", 179 | "p3-poseidon2", 180 | "p3-symmetric", 181 | "rand", 182 | "serde", 183 | ] 184 | 185 | [[package]] 186 | name = "p3-dft" 187 | version = "0.2.0-succinct" 188 | source = "registry+https://github.com/rust-lang/crates.io-index" 189 | checksum = "292e97d02d4c38d8b306c2b8c0428bf15f4d32a11a40bcf80018f675bf33267e" 190 | dependencies = [ 191 | "p3-field", 192 | "p3-matrix", 193 | "p3-maybe-rayon", 194 | "p3-util", 195 | "tracing", 196 | ] 197 | 198 | [[package]] 199 | name = "p3-field" 200 | version = "0.2.0-succinct" 201 | source = "registry+https://github.com/rust-lang/crates.io-index" 202 | checksum = "f91d8e5f9ede1171adafdb0b6a0df1827fbd4eb6a6217bfa36374e5d86248757" 203 | dependencies = [ 204 | "itertools", 205 | "num-bigint", 206 | "num-traits", 207 | "p3-util", 208 | "rand", 209 | "serde", 210 | ] 211 | 212 | [[package]] 213 | name = "p3-matrix" 214 | version = "0.2.0-succinct" 215 | source = "registry+https://github.com/rust-lang/crates.io-index" 216 | checksum = "98bf2c7680b8e906a5e147fe4ceb05a11cc9fa35678aa724333bcb35c72483c1" 217 | dependencies = [ 218 | "itertools", 219 | "p3-field", 220 | "p3-maybe-rayon", 221 | "p3-util", 222 | "rand", 223 | "serde", 224 | "tracing", 225 | ] 226 | 227 | [[package]] 228 | name = "p3-maybe-rayon" 229 | version = "0.2.0" 230 | source = "registry+https://github.com/rust-lang/crates.io-index" 231 | checksum = "3925562a4c03183eafc92fd07b19f65ac6cb4b48d68c3920ce58d9bee6efe362" 232 | 233 | [[package]] 234 | name = "p3-mds" 235 | version = "0.2.0-succinct" 236 | source = "registry+https://github.com/rust-lang/crates.io-index" 237 | checksum = "706cea48976f54702dc68dffa512684c1304d1a3606cadea423cfe0b1ee25134" 238 | dependencies = [ 239 | "itertools", 240 | "p3-dft", 241 | "p3-field", 242 | "p3-matrix", 243 | "p3-symmetric", 244 | "p3-util", 245 | "rand", 246 | ] 247 | 248 | [[package]] 249 | name = "p3-poseidon2" 250 | version = "0.2.0-succinct" 251 | source = "registry+https://github.com/rust-lang/crates.io-index" 252 | checksum = "a2ce5f5ec7f1ba3a233a671621029def7bd416e7c51218c9d1167d21602cf312" 253 | dependencies = [ 254 | "gcd", 255 | "p3-field", 256 | "p3-mds", 257 | "p3-symmetric", 258 | "rand", 259 | "serde", 260 | ] 261 | 262 | [[package]] 263 | name = "p3-symmetric" 264 | version = "0.2.0-succinct" 265 | source = "registry+https://github.com/rust-lang/crates.io-index" 266 | checksum = "2f29dc5bb6c99d3de75869d5c086874b64890280eeb7d3e068955f939e219253" 267 | dependencies = [ 268 | "itertools", 269 | "p3-field", 270 | "serde", 271 | ] 272 | 273 | [[package]] 274 | name = "p3-util" 275 | version = "0.2.0" 276 | source = "registry+https://github.com/rust-lang/crates.io-index" 277 | checksum = "88dd5ca3eb6ff33cb20084778c32a6d68064a1913b4632437408c5a1098408b3" 278 | dependencies = [ 279 | "serde", 280 | ] 281 | 282 | [[package]] 283 | name = "pin-project-lite" 284 | version = "0.2.15" 285 | source = "registry+https://github.com/rust-lang/crates.io-index" 286 | checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" 287 | 288 | [[package]] 289 | name = "ppv-lite86" 290 | version = "0.2.20" 291 | source = "registry+https://github.com/rust-lang/crates.io-index" 292 | checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" 293 | dependencies = [ 294 | "zerocopy", 295 | ] 296 | 297 | [[package]] 298 | name = "proc-macro2" 299 | version = "1.0.92" 300 | source = "registry+https://github.com/rust-lang/crates.io-index" 301 | checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" 302 | dependencies = [ 303 | "unicode-ident", 304 | ] 305 | 306 | [[package]] 307 | name = "quote" 308 | version = "1.0.38" 309 | source = "registry+https://github.com/rust-lang/crates.io-index" 310 | checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" 311 | dependencies = [ 312 | "proc-macro2", 313 | ] 314 | 315 | [[package]] 316 | name = "rand" 317 | version = "0.8.5" 318 | source = "registry+https://github.com/rust-lang/crates.io-index" 319 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 320 | dependencies = [ 321 | "libc", 322 | "rand_chacha", 323 | "rand_core", 324 | ] 325 | 326 | [[package]] 327 | name = "rand_chacha" 328 | version = "0.3.1" 329 | source = "registry+https://github.com/rust-lang/crates.io-index" 330 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 331 | dependencies = [ 332 | "ppv-lite86", 333 | "rand_core", 334 | ] 335 | 336 | [[package]] 337 | name = "rand_core" 338 | version = "0.6.4" 339 | source = "registry+https://github.com/rust-lang/crates.io-index" 340 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 341 | dependencies = [ 342 | "getrandom", 343 | ] 344 | 345 | [[package]] 346 | name = "serde" 347 | version = "1.0.217" 348 | source = "registry+https://github.com/rust-lang/crates.io-index" 349 | checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" 350 | dependencies = [ 351 | "serde_derive", 352 | ] 353 | 354 | [[package]] 355 | name = "serde_derive" 356 | version = "1.0.217" 357 | source = "registry+https://github.com/rust-lang/crates.io-index" 358 | checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" 359 | dependencies = [ 360 | "proc-macro2", 361 | "quote", 362 | "syn", 363 | ] 364 | 365 | [[package]] 366 | name = "sha2" 367 | version = "0.10.8" 368 | source = "registry+https://github.com/rust-lang/crates.io-index" 369 | checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" 370 | dependencies = [ 371 | "cfg-if", 372 | "cpufeatures", 373 | "digest", 374 | ] 375 | 376 | [[package]] 377 | name = "sha2" 378 | version = "0.10.8" 379 | source = "git+https://github.com/sp1-patches/RustCrypto-hashes?tag=patch-sha2-0.10.8-sp1-4.0.0-rc.3#1f224388fdede7cef649bce0d63876d1a9e3f515" 380 | dependencies = [ 381 | "cfg-if", 382 | "cpufeatures", 383 | "digest", 384 | ] 385 | 386 | [[package]] 387 | name = "sha256-sp1" 388 | version = "0.1.0" 389 | dependencies = [ 390 | "serde", 391 | "sha2 0.10.8 (git+https://github.com/sp1-patches/RustCrypto-hashes?tag=patch-sha2-0.10.8-sp1-4.0.0-rc.3)", 392 | "sp1-zkvm", 393 | ] 394 | 395 | [[package]] 396 | name = "sp1-lib" 397 | version = "4.0.1" 398 | source = "registry+https://github.com/rust-lang/crates.io-index" 399 | checksum = "aac3d3deeed25e9cad80e4275faf5954aa63f213ed3422f0e098dd2d0c1b0c0e" 400 | dependencies = [ 401 | "bincode", 402 | "serde", 403 | "sp1-primitives", 404 | ] 405 | 406 | [[package]] 407 | name = "sp1-primitives" 408 | version = "4.0.1" 409 | source = "registry+https://github.com/rust-lang/crates.io-index" 410 | checksum = "09b25a09b455dfae9c688da05718b205e8bd4afab36cd912d54639f5d4035815" 411 | dependencies = [ 412 | "bincode", 413 | "hex", 414 | "lazy_static", 415 | "num-bigint", 416 | "p3-baby-bear", 417 | "p3-field", 418 | "p3-poseidon2", 419 | "p3-symmetric", 420 | "serde", 421 | "sha2 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)", 422 | ] 423 | 424 | [[package]] 425 | name = "sp1-zkvm" 426 | version = "4.0.1" 427 | source = "registry+https://github.com/rust-lang/crates.io-index" 428 | checksum = "f971db10d58b13c9a5d8cee4f7d1195d6f8a2debb9c33bd67f4eea5817432d42" 429 | dependencies = [ 430 | "cfg-if", 431 | "getrandom", 432 | "lazy_static", 433 | "libm", 434 | "rand", 435 | "sha2 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)", 436 | "sp1-lib", 437 | "sp1-primitives", 438 | ] 439 | 440 | [[package]] 441 | name = "syn" 442 | version = "2.0.94" 443 | source = "registry+https://github.com/rust-lang/crates.io-index" 444 | checksum = "987bc0be1cdea8b10216bd06e2ca407d40b9543468fafd3ddfb02f36e77f71f3" 445 | dependencies = [ 446 | "proc-macro2", 447 | "quote", 448 | "unicode-ident", 449 | ] 450 | 451 | [[package]] 452 | name = "tracing" 453 | version = "0.1.41" 454 | source = "registry+https://github.com/rust-lang/crates.io-index" 455 | checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" 456 | dependencies = [ 457 | "pin-project-lite", 458 | "tracing-attributes", 459 | "tracing-core", 460 | ] 461 | 462 | [[package]] 463 | name = "tracing-attributes" 464 | version = "0.1.28" 465 | source = "registry+https://github.com/rust-lang/crates.io-index" 466 | checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" 467 | dependencies = [ 468 | "proc-macro2", 469 | "quote", 470 | "syn", 471 | ] 472 | 473 | [[package]] 474 | name = "tracing-core" 475 | version = "0.1.33" 476 | source = "registry+https://github.com/rust-lang/crates.io-index" 477 | checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" 478 | dependencies = [ 479 | "once_cell", 480 | ] 481 | 482 | [[package]] 483 | name = "typenum" 484 | version = "1.17.0" 485 | source = "registry+https://github.com/rust-lang/crates.io-index" 486 | checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" 487 | 488 | [[package]] 489 | name = "unicode-ident" 490 | version = "1.0.14" 491 | source = "registry+https://github.com/rust-lang/crates.io-index" 492 | checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" 493 | 494 | [[package]] 495 | name = "version_check" 496 | version = "0.9.5" 497 | source = "registry+https://github.com/rust-lang/crates.io-index" 498 | checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 499 | 500 | [[package]] 501 | name = "wasi" 502 | version = "0.11.0+wasi-snapshot-preview1" 503 | source = "registry+https://github.com/rust-lang/crates.io-index" 504 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 505 | 506 | [[package]] 507 | name = "zerocopy" 508 | version = "0.7.35" 509 | source = "registry+https://github.com/rust-lang/crates.io-index" 510 | checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" 511 | dependencies = [ 512 | "byteorder", 513 | "zerocopy-derive", 514 | ] 515 | 516 | [[package]] 517 | name = "zerocopy-derive" 518 | version = "0.7.35" 519 | source = "registry+https://github.com/rust-lang/crates.io-index" 520 | checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" 521 | dependencies = [ 522 | "proc-macro2", 523 | "quote", 524 | "syn", 525 | ] 526 | -------------------------------------------------------------------------------- /programs/sha256-sp1/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | [package] 3 | name = "sha256-sp1" 4 | version = "0.1.0" 5 | edition = "2021" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | sp1-zkvm = "4.0.0-rc.10" 11 | serde = { version = "1.0.204", default-features = false, features = ["derive"] } 12 | sha2 = { git = "https://github.com/sp1-patches/RustCrypto-hashes", package = "sha2", tag = "patch-sha2-0.10.8-sp1-4.0.0-rc.3" } 13 | 14 | [features] 15 | risc0 = [] 16 | sp1 = [] 17 | 18 | [patch] 19 | -------------------------------------------------------------------------------- /programs/sha256-sp1/elf/riscv32im-succinct-zkvm-elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/succinctlabs/zkvm-perf/861cc5c18e3e31ae080640877642ce818e7eaff4/programs/sha256-sp1/elf/riscv32im-succinct-zkvm-elf -------------------------------------------------------------------------------- /programs/sha256-sp1/src/main.rs: -------------------------------------------------------------------------------- 1 | // This code is borrowed from RISC Zero's benchmarks. 2 | // 3 | // Copyright 2024 RISC Zero, Inc. 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | 17 | #![no_main] 18 | 19 | use sha2::{Digest, Sha256}; 20 | 21 | sp1_zkvm::entrypoint!(main); 22 | 23 | fn main() { 24 | let data: Vec = sp1_zkvm::io::read(); 25 | let mut hasher = Sha256::new(); 26 | hasher.update(&data); 27 | let hash = hasher.finalize(); 28 | sp1_zkvm::io::commit(&hash.to_vec()) 29 | } -------------------------------------------------------------------------------- /programs/ssz-withdrawals/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | [package] 3 | version = "0.1.0" 4 | name = "ssz-withdrawals" 5 | edition = "2021" 6 | 7 | [dependencies] 8 | sp1-zkvm = "4.0.0-rc.10" 9 | hex-literal = "0.4.1" 10 | sha2 = "0.9.8" 11 | sha2_risc0 = { package = "sha2", git = "https://github.com/risc0/RustCrypto-hashes", tag = "sha2-v0.10.6-risczero.0" } 12 | sha2_sp1 = { git = "https://github.com/sp1-patches/RustCrypto-hashes", package = "sha2", tag = "patch-sha2-0.10.8-sp1-4.0.0-rc.3" } 13 | ssz_rs = { version = "0.9.0", features = ["serde"] } 14 | serde_json = "1.0.111" 15 | hex = "0.4.3" 16 | serde_with = { version = "3.4.0", features = ["hex"] } 17 | serde = { version = "1.0.204", default-features = false, features = ["derive"] } 18 | alloy-primitives = "0.6.0" 19 | cfg-if = "1.0.0" 20 | risc0-zkvm = { version = "=1.2.1", default-features = false, features = ["std", "unstable"] } 21 | 22 | [features] 23 | sp1 = [] 24 | risc0 = [] 25 | -------------------------------------------------------------------------------- /programs/ssz-withdrawals/elf/riscv32im-succinct-zkvm-elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/succinctlabs/zkvm-perf/861cc5c18e3e31ae080640877642ce818e7eaff4/programs/ssz-withdrawals/elf/riscv32im-succinct-zkvm-elf -------------------------------------------------------------------------------- /programs/ssz-withdrawals/src/beacon/hints.rs: -------------------------------------------------------------------------------- 1 | use crate::beacon::types::*; 2 | use crate::beacon::{branch_from_bytes, node_from_bytes}; 3 | use hex_literal::hex; 4 | use ssz_rs::prelude::*; 5 | use std::hint::black_box; 6 | 7 | // TODO: Read real data in all of these hints by reading it from outside of the zkvm. 8 | 9 | /// Returns the beaacon block's withdrawals root and a corresponding SSZ merkle proof. 10 | pub fn withdrawals_root_proof(_block_root: Node) -> (Node, Vec) { 11 | let leaf = node_from_bytes(hex!( 12 | "5cc52fb136d9ff526f071f8f87d44c3f35ff5dc973371a2c3613d8ecc53bfcd4" 13 | )); 14 | let branch = branch_from_bytes( 15 | [ 16 | hex!("0000000000000000000000000000000000000000000000000000000000000000"), 17 | hex!("8d72069921728c6688441d7cb5dab79812429013ac09311d5456aa61b770084d"), 18 | hex!("f43b91870f20fa578621b1921572b2497f1800a0b46ba5fcd62b55b625484a62"), 19 | hex!("0e7b89b1f002a34b400823b237859832c120a514d21f30de6c41cd4693fbc82a"), 20 | hex!("1912b846656eeebcbe7f442b1e790abfd786a87c51f5065c9313e58d2a982ca5"), 21 | hex!("336488033fe5f3ef4ccc12af07b9370b92e553e35ecb4a337a1b1c0e4afe1e0e"), 22 | hex!("db56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d71"), 23 | hex!("8841ee1abbf9a4767cafd94441333031d3a72774bbb5da4d848e1fec08a840e6"), 24 | hex!("0000000000000000000000000000000000000000000000000000000000000000"), 25 | hex!("f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b"), 26 | hex!("3ca168014d8da18c223f9f3cbbad902cd2ffabaeef25d3ff32b0d51984231409"), 27 | ] 28 | .as_slice(), 29 | ); 30 | 31 | (leaf, branch) 32 | } 33 | 34 | /// Given a block root and index [0, 16), returns the withdrawal and a corresponding SSZ proof. 35 | pub fn withdrawal_proof(_block_root: Node, _index: u32) -> (Withdrawal, Vec) { 36 | let withdrawal = Withdrawal { 37 | index: 26081110, 38 | validator_index: 795049, 39 | address: ExecutionAddress::try_from( 40 | hex!("4bbeae4ca5c6f79a1bc7db315bb6f2c90ebbb4cc").to_vec(), 41 | ) 42 | .unwrap(), 43 | amount: 17122745, 44 | }; 45 | 46 | let branch = branch_from_bytes(black_box( 47 | [ 48 | hex!("cf4999288497e7a3ee17c8251a26ac3ae91bc6b7ac5a2ad42df15807d4aaa99d"), 49 | hex!("cad0401190b985bede55534962ab9700e57f95d7da447969e842507404427e39"), 50 | hex!("a98e59035f016b68eabde1d90e7e617dac80b0ec72931f30261e3c53ae9d1999"), 51 | hex!("10de9d131acb9a2dba0843ce3dc101116d3043f4aa1a3f8f5c0b053d7d9c7d46"), 52 | hex!("1000000000000000000000000000000000000000000000000000000000000000"), 53 | ] 54 | .as_slice(), 55 | )); 56 | 57 | (withdrawal, branch) 58 | } 59 | 60 | /// Returns the corresponding beacon block header. 61 | pub fn beacon_header_proof(_block_root: Node) -> BeaconBlockHeader { 62 | // TODO: read real data from hint 63 | BeaconBlockHeader { 64 | slot: 8225000, 65 | proposer_index: 980811, 66 | parent_root: node_from_bytes(hex!( 67 | "6a8edd0d02c6195037bfab129783fb9847d88e7587a3b097fdc4eb5cb0da7a16" 68 | )), 69 | state_root: node_from_bytes(hex!( 70 | "02b054e25cfa96a82e7d133c0f469dcfd1661fd75203a612f17dfe2f4bdb956a" 71 | )), 72 | body_root: node_from_bytes(hex!( 73 | "ca1a1e5f480a739b8e276db2f67f8ea399955604ad1479d748bd6912029e9dd8" 74 | )), 75 | } 76 | } 77 | 78 | /// Returns the beacon block's validators root and a corresponding SSZ merkle proof. 79 | pub fn validators_root_proof(_block_root: Node) -> (Node, Vec) { 80 | let leaf = Node::try_from( 81 | hex!("8ada0d639d94919c8a8aa62f13bbf5f0a0bf3e4340aa01679e533a4f68a54dc0").as_slice(), 82 | ) 83 | .unwrap(); 84 | let branch = branch_from_bytes( 85 | [ 86 | hex!("b27b100000000000000000000000000000000000000000000000000000000000"), 87 | hex!("e5da071085e819357fd4a416416e21fe9a679b382da47c5acb3abe5b756c1958"), 88 | hex!("2ed0e7ad478ad9368bf451f3df6ef082094e9dd2d830c441fae41ebfebc84dc4"), 89 | hex!("45f160b40030ff5f85164e1cae445f13360c820f5194f38d3ba7f0cad08cf573"), 90 | hex!("e6e49e7d4ebc221a8cc193b623a260de6c91fa8382e40dbd50ce6c898252545d"), 91 | hex!("34d8f1f1afe3c688cdc9a4b94bc50ffadc065df2156a60606c8e629a4ea55add"), 92 | hex!("9d1b8e00a8c76b185d2f4322432eee0d5797f1da0c4b9a9ab4d9ba04460b3ab9"), 93 | hex!("d2c3e8005d0f60900b02e681738404360529c5f28c34160abc3e639c651ec391"), 94 | ] 95 | .as_slice(), 96 | ); 97 | 98 | (leaf, branch) 99 | } 100 | 101 | /// Returns the corresponding validator and SSZ proof. 102 | pub fn validator_proof(_block_root: Node, _index: u64) -> (Validator, Vec) { 103 | let validator = Validator { 104 | pubkey: Vector::try_from(hex!("b005012bfc4a0d6fd04d0479724b7aeb64462d558bb9b731e47c6d0b5999a12b77f8a4f7724aa87aaf586a5bfc831c80").to_vec()).unwrap(), 105 | withdrawal_credentials: node_from_bytes(hex!("0100000000000000000000004bbeae4ca5c6f79a1bc7db315bb6f2c90ebbb4cc")), 106 | effective_balance: 32000000000, 107 | slashed: false, 108 | activation_eligibility_epoch: 210209, 109 | activation_epoch: 219962, 110 | exit_epoch: 18446744073709551615, 111 | withdrawable_epoch: 18446744073709551615, 112 | }; 113 | 114 | let branch = branch_from_bytes( 115 | [ 116 | hex!("e075356f0de5a8ada345cfbc659e02600c381c2de2e62dbce0ff1532f3c58d07"), 117 | hex!("321356d9f54c30b2ef61708679aeb3dd2747e6c2502d566fb04f7c404b4c76d2"), 118 | hex!("ed8f2e00df064fb7eb985a24825d94d44c265955bd25400a31167202b42c96c7"), 119 | hex!("bab082567b013beef822eb0555ff721c9790dfccde04d5905053bf88eb3b1d91"), 120 | hex!("f95a768cd1fe077a8af4e44ec1a6eb3913df1ea1d5c12a3a2d1381b9fd5000ec"), 121 | hex!("d94aa0337fc162c0ca7d3eaf2a06cbe98fab5f5fd44a5116db9613930906c861"), 122 | hex!("040d7a1711a2df276af4b44196786779055b8beb4d161017a31f0ea121084913"), 123 | hex!("1d3507adbf5e08b29af66b27fb11cf0116965c3d1c72599ee1e8447aa0d7a831"), 124 | hex!("7ef44a0663996c241ccfe000c247568cfe2ac95d2ff0181818e13e1d25b5d82b"), 125 | hex!("be3d37cbfcc80f6cb90affd827148b8ec4a84999f63e3a541728269dd2b81d74"), 126 | hex!("742bfcc2c2e291e770a2f0f957e4a73bc5f0e6a4b3ac920a671c4bb63f4ad06f"), 127 | hex!("d54b2a971f8cfd672117ce8399f42a58e0a5db5ae8a4158f0102628c700fc433"), 128 | hex!("7313386734714b621b6e0b6d287b4f68c0a411a744bff857a43b492ed8c0f938"), 129 | hex!("74c0164db9880076c4c9142f3acc8689e322342a61886c7129f75b00ac8a80c1"), 130 | hex!("3ce51b360e4a8a13823be7b4a8b2b41e779b1f68c79fbf5d53f1e527d054ce57"), 131 | hex!("b0ba4d4679795524aa4336728c637fc130fdebde617b4ed082d04e5cc82371e3"), 132 | hex!("21a52516163bb5f063a240b59557bbf15225fe3cdd4044a446ffe2c7474fa512"), 133 | hex!("679adcc02052f3ae34d1dce4cb01120ec9fa67a7ee6a43d3eeea993c01266245"), 134 | hex!("ad33934639a9aa33b5ba84b4f1875b1e4e1230d75b1127eb33bd8ae7b8cb5d7c"), 135 | hex!("84c2ac0410a9b555e8ab56138015c847037f837776a82dcfbf7a5ceebe6660d9"), 136 | hex!("cddba7b592e3133393c16194fac7431abf2f5485ed711db282183c819e08ebaa"), 137 | hex!("8a8d7fe3af8caa085a7639a832001457dfb9128a8061142ad0335629ff23ff9c"), 138 | hex!("feb3c337d7a51a6fbf00b9e34c52e1c9195c969bd4e7a0bfd51d5c5bed9c1167"), 139 | hex!("e71f0aa83cc32edfbefa9f4d3e0174ca85182eec9f3a09f6a6c0df6377a510d7"), 140 | hex!("31206fa80a50bb6abe29085058f16212212a60eec8f049fecb92d8c8e0a84bc0"), 141 | hex!("21352bfecbeddde993839f614c3dac0a3ee37543f9b412b16199dc158e23b544"), 142 | hex!("619e312724bb6d7c3153ed9de791d764a366b389af13c58bf8a8d90481a46765"), 143 | hex!("7cdd2986268250628d0c10e385c58c6191e6fbe05191bcc04f133f2cea72c1c4"), 144 | hex!("848930bd7ba8cac54661072113fb278869e07bb8587f91392933374d017bcbe1"), 145 | hex!("8869ff2c22b28cc10510d9853292803328be4fb0e80495e8bb8d271f5b889636"), 146 | hex!("b5fe28e79f1b850f8658246ce9b6a1e7b49fc06db7143e8fe0b4f2b0c5523a5c"), 147 | hex!("985e929f70af28d0bdd1a90a808f977f597c7c778c489e98d3bd8910d31ac0f7"), 148 | hex!("c6f67e02e6e4e1bdefb994c6098953f34636ba2b6ca20a4721d2b26a886722ff"), 149 | hex!("1c9a7e5ff1cf48b4ad1582d3f4e4a1004f3b20d8c5a2b71387a4254ad933ebc5"), 150 | hex!("2f075ae229646b6f6aed19a5e372cf295081401eb893ff599b3f9acc0c0d3e7d"), 151 | hex!("328921deb59612076801e8cd61592107b5c67c79b846595cc6320c395b46362c"), 152 | hex!("bfb909fdb236ad2411b4e4883810a074b840464689986c3f8a8091827e17c327"), 153 | hex!("55d8fb3687ba3ba49f342c77f5a1f89bec83d811446e1a467139213d640b6a74"), 154 | hex!("f7210d4f8e7e1039790e7bf4efa207555a10a6db1dd4b95da313aaa88b88fe76"), 155 | hex!("ad21b516cbc645ffe34ab5de1c8aef8cd4e7f8d2b51e8e1456adc7563cda206f"), 156 | hex!("e0f50f0000000000000000000000000000000000000000000000000000000000"), 157 | ] 158 | .as_slice(), 159 | ); 160 | 161 | (validator, branch) 162 | } 163 | 164 | // TODO: Historical block root functions may look slightly different with real data 165 | 166 | /// Return the historical summary root containing the target slot and a corresponding SSZ proof. The 167 | /// target slot must be at most (source_slot - 8192). 168 | pub fn historical_far_slot_proof(_block_root: Node, _target_slot: u64) -> (Node, Vec) { 169 | // Block root -> historical summary root 170 | let leaf = node_from_bytes(hex!( 171 | "1d52ab18adbab483661ee3dd7ebc62691abe30c1ac619a120a4d3050ec0f7c4b" 172 | )); 173 | let branch = branch_from_bytes( 174 | [ 175 | hex!("71d67d25484adcd645fc49c83f48a44b2f95c6215356a6f858549ef5ce0fd141"), 176 | hex!("7edb31a2db983bbef421217131d3073e1c1c34cafad08374f39c8b51850ca907"), 177 | hex!("7bd21503c7a2dc1c39f132639fd6a28aa2fad590d0b0b14a1b4b177b39f69b1c"), 178 | hex!("c2989830254dad6751f97da47fcdf8a6cca5179e5b8a1b000562382b9523808d"), 179 | hex!("13f3e6cee244b2a1854f29254223e898db082331faa7a04363eb7ab779f44166"), 180 | hex!("1b1f565fde7046ec5164668459a1906eb9239d83d62869f97fdb0051b3986615"), 181 | hex!("a8fb6dc98b7b638c5f0f39134e8b545dd7b1f5f924fda80247eb432bb098d53b"), 182 | hex!("8793464b9aec0216b2b2fd8721d5377602722287b548a4370cb44654233752e0"), 183 | hex!("26846476fd5fc54a5d43385167c95144f2643f533cc85bb9d16b782f8d7db193"), 184 | hex!("506d86582d252405b840018792cad2bf1259f1ef5aa5f887e13cb2f0094f51e1"), 185 | hex!("ffff0ad7e659772f9534c195c815efc4014ef1e1daed4404c06385d11192e92b"), 186 | hex!("6cf04127db05441cd833107a52be852868890e4317e6a02ab47683aa75964220"), 187 | hex!("b7d05f875f140027ef5118a2247bbb84ce8f2f0f1123623085daf7960c329f5f"), 188 | hex!("df6af5f5bbdb6be9ef8aa618e4bf8073960867171e29676f8b284dea6a08a85e"), 189 | hex!("b58d900f5e182e3c50ef74969ea16c7726c549757cc23523c369587da7293784"), 190 | hex!("d49a7502ffcfb0340b1d7885688500ca308161a7f96b62df9d083b71fcc8f2bb"), 191 | hex!("8fe6b1689256c0d385f42f5bbe2027a22c1996e110ba97c171d3e5948de92beb"), 192 | hex!("8d0d63c39ebade8509e0ae3c9c3876fb5fa112be18f905ecacfecb92057603ab"), 193 | hex!("95eec8b2e541cad4e91de38385f2e046619f54496c2382cb6cacd5b98c26f5a4"), 194 | hex!("f893e908917775b62bff23294dbbe3a1cd8e6cc1c35b4801887b646a6f81f17f"), 195 | hex!("cddba7b592e3133393c16194fac7431abf2f5485ed711db282183c819e08ebaa"), 196 | hex!("8a8d7fe3af8caa085a7639a832001457dfb9128a8061142ad0335629ff23ff9c"), 197 | hex!("feb3c337d7a51a6fbf00b9e34c52e1c9195c969bd4e7a0bfd51d5c5bed9c1167"), 198 | hex!("e71f0aa83cc32edfbefa9f4d3e0174ca85182eec9f3a09f6a6c0df6377a510d7"), 199 | hex!("f600000000000000000000000000000000000000000000000000000000000000"), 200 | hex!("13d8050000000000000000000000000000000000000000000000000000000000"), 201 | hex!("431f12da5c99f901a543ca43ce3bf81d27aa2ca768dff91a57f4f7315e58ed34"), 202 | hex!("db56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d71"), 203 | hex!("7065b5a85d89a8283552e82ee1e2638930cb77006062b2e0c1ef1a0d565d3b80"), 204 | hex!("12c7dbcbe2f85d52225951cc7581dc333c64eb538a4757552763d986f696ac15"), 205 | hex!("6a8edd0d02c6195037bfab129783fb9847d88e7587a3b097fdc4eb5cb0da7a16"), 206 | hex!("2766cb64d6adc5d69310000d535c140372ff879bc9dee329db746de3665c6b10"), 207 | hex!("e53131a68915218beddb79d3233e18e208775b90f32457414253f88e5e7320fa"), 208 | ] 209 | .as_slice(), 210 | ); 211 | (leaf, branch) 212 | } 213 | 214 | /// Given a block root and target slot, return the target block root and a corresponding SSZ merkle 215 | /// proof from historical summary root to target block root. The target slot must be at most 216 | /// (source_slot - 8192). 217 | pub fn historical_far_slot_blockroot_proof( 218 | _block_root: Node, 219 | _target_slot: u64, 220 | ) -> (Node, Vec) { 221 | let leaf = node_from_bytes(hex!( 222 | "baa0d6d6383b6c227a59bd739d6adda29db2bbebc7db7a1d33f76d713c25be92" 223 | )); 224 | let branch = branch_from_bytes( 225 | [ 226 | hex!("c1335f53786cb473466d9e876f516e6fcf0c92fc584f1b04e382d5ff97a079a1"), 227 | hex!("3d97b9db50d76b323da4c6158627655cc08f312d20fa87891fe920f573e4dd0f"), 228 | hex!("bde4d4740ab0e58de6b544b0a07afa84dbcfaaf44de9622fed066ac4d1cc3528"), 229 | hex!("0d11c3f316880e9b435329f1614a5b0352aac1d6380394082b4c3efb3257aed2"), 230 | hex!("f1c253201bf508628075aa2c22de836695e488706491aa18f5791dac22a4945f"), 231 | hex!("27e1509081c6dce997920310354ea7b761ad9d4769d1d7c08af9dca9b6a8c5a4"), 232 | hex!("ac2097ec57fa31b30c79a6a9c992c70981ecbe28094f6fb093deeb036484a979"), 233 | hex!("67b3ddc88691307694988dd9a00d7843c6f5ac472b8de33dbbb5e6b9782d12a3"), 234 | hex!("3991d8ed56935aa73979411a92de0f76a48605f4eb3bdff3a0a8f3537856a512"), 235 | hex!("3506c644cad38ea2ff4c047350ceabaefed7459f643613458b99c2ff0417c23f"), 236 | hex!("018eeb10177703946d889cc270df7681c9239d6affd88edd123cef235cf95648"), 237 | hex!("0f43d0bd83d6ce190650d5453d89a61b211ea7893634760a7d143e212de2e24b"), 238 | hex!("df4ca4136a2adad654f3614629ee0845cb4059f7fbb1ecfc6e278e0914510201"), 239 | hex!("9b3b8a195299c1fbcbbb0e526cbb0f831c7641170d21ff013df86c3e94db49b4"), 240 | ] 241 | .as_slice(), 242 | ); 243 | (leaf, branch) 244 | } 245 | 246 | /// Returns withdrawal slots, withdrawal indexes, and validator indexes that match the given withdrawal address. 247 | pub fn withdrawals_range( 248 | _block_root: Node, 249 | _start_slot: u64, 250 | _end_slot: u64, 251 | _withdrawal_address: &ExecutionAddress, 252 | ) -> (Vec<(u64, Vec)>, Vec) { 253 | ( 254 | vec![ 255 | ( 256 | 7855804, 257 | vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], 258 | ), 259 | ( 260 | 7855805, 261 | vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], 262 | ), 263 | ( 264 | 7855806, 265 | vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], 266 | ), 267 | ], 268 | vec![795049, 795050, 795051], 269 | ) 270 | } 271 | -------------------------------------------------------------------------------- /programs/ssz-withdrawals/src/beacon/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod hints; 2 | pub mod prove; 3 | pub mod types; 4 | mod utils; 5 | pub use utils::*; 6 | -------------------------------------------------------------------------------- /programs/ssz-withdrawals/src/beacon/prove.rs: -------------------------------------------------------------------------------- 1 | use crate::beacon::hints; 2 | use crate::beacon::is_valid_merkle_big_branch; 3 | use crate::beacon::types::*; 4 | use ssz_rs::prelude::*; 5 | use std::hint::black_box; 6 | use std::str::FromStr; 7 | 8 | // TODO: Assert or return validity in these functions when using real data 9 | 10 | pub fn block_header(block_root: Node) -> BeaconBlockHeader { 11 | let mut header = black_box(hints::beacon_header_proof(block_root)); 12 | 13 | let header_root = black_box(header.hash_tree_root().unwrap()); 14 | println!("header root: {:?}", header_root); 15 | 16 | // TODO: with real data, assert that header_root == block_root 17 | // assert_eq!(header_root, block_root); 18 | 19 | header 20 | } 21 | 22 | pub fn withdrawals_root(block_root: Node) -> Node { 23 | let (leaf, branch) = black_box(hints::withdrawals_root_proof(block_root)); 24 | let depth = 11; 25 | let index = alloy_primitives::U256::from(3230); 26 | 27 | let valid = black_box(is_valid_merkle_big_branch( 28 | &leaf, 29 | branch.iter(), 30 | depth, 31 | index, 32 | &block_root, 33 | )); 34 | println!("withdrawals root valid: {}", valid); 35 | leaf 36 | } 37 | 38 | pub fn withdrawal(block_root: Node, withdrawals_root: Node, index: u32) -> Withdrawal { 39 | let (mut withdrawal, branch) = black_box(hints::withdrawal_proof(block_root, index)); 40 | let leaf = withdrawal.hash_tree_root().unwrap(); 41 | let depth = 5; 42 | let index = alloy_primitives::U256::from(32); 43 | 44 | let valid = black_box(is_valid_merkle_big_branch( 45 | &leaf, 46 | branch.iter(), 47 | depth, 48 | index, 49 | &withdrawals_root, 50 | )); 51 | println!("withdrawal valid: {}", valid); 52 | withdrawal 53 | } 54 | 55 | pub fn validators_root(block_root: Node) -> Node { 56 | let (leaf, branch) = black_box(hints::validators_root_proof(block_root)); 57 | let depth = 8; 58 | let index = alloy_primitives::U256::from(363); 59 | // let root = node_from_bytes(hex!( 60 | // "88d257af10bc873ab8e41bfb9fd51be55249f78549ea0dbaa0c2deda979368e7" 61 | // )); 62 | 63 | let valid = black_box(is_valid_merkle_big_branch( 64 | &leaf, 65 | branch.iter(), 66 | depth, 67 | index, 68 | &block_root, 69 | )); 70 | println!("validators root valid: {}", valid); 71 | leaf 72 | } 73 | 74 | pub fn validator(block_root: Node, validators_root: Node, validator_index: u64) -> Validator { 75 | let (mut validator, branch) = black_box(hints::validator_proof(block_root, validator_index)); 76 | let leaf = validator.hash_tree_root().unwrap(); 77 | let depth = 41; 78 | // ssz.phase0.Validators.getPathInfo([0]).gindex 79 | let index = alloy_primitives::U256::from_str("2199023255552") 80 | .unwrap() 81 | .wrapping_add(alloy_primitives::U256::from(validator_index)); 82 | // let root = node_from_bytes(hex!( 83 | // "8ada0d639d94919c8a8aa62f13bbf5f0a0bf3e4340aa01679e533a4f68a54dc0" 84 | // )); 85 | let valid = black_box(is_valid_merkle_big_branch( 86 | &leaf, 87 | branch.iter(), 88 | depth, 89 | index, 90 | &validators_root, 91 | )); 92 | println!("validator valid: {}", valid); 93 | validator 94 | } 95 | 96 | pub fn historical_far_slot(block_root: Node, target_slot: u64) -> Node { 97 | let (leaf, branch) = black_box(hints::historical_far_slot_proof(block_root, target_slot)); 98 | let depth = 33; 99 | let array_index = (target_slot - 6209536) / 8192; 100 | let index = alloy_primitives::U256::from_str("12717129728") 101 | .unwrap() 102 | .wrapping_add(alloy_primitives::U256::from(array_index)); 103 | // let root = node_from_bytes(hex!( 104 | // "d00c4da1a3ad4d42bd35f128544227d19e163194569d69d54a3d14112e3c897c" 105 | // )); 106 | 107 | let valid = black_box(is_valid_merkle_big_branch( 108 | &leaf, 109 | branch.iter(), 110 | depth, 111 | index, 112 | &block_root, 113 | )); 114 | println!("historical far slot valid: {}", valid); 115 | leaf 116 | } 117 | 118 | fn historical_far_slot_blockroot(block_root: Node, summary_root: Node, target_slot: u64) -> Node { 119 | let (leaf, branch) = black_box(hints::historical_far_slot_blockroot_proof( 120 | block_root, 121 | target_slot, 122 | )); 123 | let depth = 14; 124 | let array_index = (target_slot) % 8192; 125 | let index = alloy_primitives::U256::from(16384 + array_index); 126 | // let root = node_from_bytes(hex!( 127 | // "1d52ab18adbab483661ee3dd7ebc62691abe30c1ac619a120a4d3050ec0f7c4b" 128 | // )); 129 | 130 | let valid = black_box(is_valid_merkle_big_branch( 131 | &leaf, 132 | branch.iter(), 133 | depth, 134 | index, 135 | &summary_root, 136 | )); 137 | println!("historical far slot blockroot valid: {}", valid); 138 | leaf 139 | } 140 | 141 | pub fn historical_block_root(block_root: Node, source_slot: u64, target_slot: u64) -> Node { 142 | if source_slot - target_slot < 8192 { 143 | unimplemented!() 144 | } else { 145 | let summary_root = historical_far_slot(block_root, target_slot); 146 | historical_far_slot_blockroot(block_root, summary_root, target_slot) 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /programs/ssz-withdrawals/src/beacon/types.rs: -------------------------------------------------------------------------------- 1 | use crate::DeserializeError; 2 | use serde; 3 | use serde_with::{serde_as, DisplayFromStr}; 4 | use ssz_rs::prelude::{Deserialize, Node, SimpleSerialize, Sized, Vector}; 5 | 6 | pub type Bytes32 = Node; 7 | pub type BLSPubkey = Vector; 8 | pub type ExecutionAddress = Vector; 9 | 10 | #[derive(PartialEq, Eq, Debug, Default, Clone, SimpleSerialize)] 11 | pub struct Validator { 12 | pub pubkey: BLSPubkey, 13 | pub withdrawal_credentials: Bytes32, 14 | pub effective_balance: u64, 15 | pub slashed: bool, 16 | pub activation_eligibility_epoch: u64, 17 | pub activation_epoch: u64, 18 | pub exit_epoch: u64, 19 | pub withdrawable_epoch: u64, 20 | } 21 | 22 | #[serde_as] 23 | #[derive( 24 | serde::Serialize, serde::Deserialize, PartialEq, Eq, Debug, Default, Clone, SimpleSerialize, 25 | )] 26 | pub struct BeaconBlockHeader { 27 | #[serde_as(as = "DisplayFromStr")] 28 | pub slot: u64, 29 | #[serde_as(as = "DisplayFromStr")] 30 | pub proposer_index: u64, 31 | pub parent_root: Bytes32, 32 | pub state_root: Bytes32, 33 | pub body_root: Bytes32, 34 | } 35 | 36 | #[serde_as] 37 | #[derive( 38 | serde::Serialize, serde::Deserialize, PartialEq, Eq, Debug, Default, Clone, SimpleSerialize, 39 | )] 40 | #[serde(rename_all = "camelCase")] 41 | pub struct Withdrawal { 42 | pub index: u64, 43 | pub validator_index: u64, 44 | #[serde_as(as = "serde_with::hex::Hex")] 45 | pub address: ExecutionAddress, 46 | #[serde_as(as = "DisplayFromStr")] 47 | pub amount: u64, 48 | } 49 | -------------------------------------------------------------------------------- /programs/ssz-withdrawals/src/beacon/utils.rs: -------------------------------------------------------------------------------- 1 | use alloy_primitives::U256; 2 | use ssz_rs::prelude::Node; 3 | 4 | cfg_if::cfg_if! { 5 | if #[cfg(feature = "sp1")] { 6 | use sha2_sp1::{Digest, Sha256}; 7 | } else if #[cfg(feature = "risc0")] { 8 | use sha2_risc0::{Digest, Sha256}; 9 | } else { 10 | use sha2::{Digest, Sha256}; 11 | } 12 | } 13 | 14 | // From https://github.com/ralexstokes/ssz-rs/blob/main/ssz-rs/src/merkleization/proofs.rs 15 | // Modified to use alloy_primitives::U256 instead of u64 for large gindex values 16 | pub fn is_valid_merkle_big_branch<'a>( 17 | leaf: &Node, 18 | mut branch: impl Iterator, 19 | depth: usize, 20 | index: U256, 21 | root: &Node, 22 | ) -> bool { 23 | let mut value: [u8; 32] = leaf.as_ref().try_into().unwrap(); 24 | let mut hasher = Sha256::new(); 25 | for i in 0..depth { 26 | let next_node = match branch.next() { 27 | Some(node) => node, 28 | None => return false, 29 | }; 30 | if index.bit(i) { 31 | hasher.update(next_node.as_ref()); 32 | hasher.update(value.as_ref()); 33 | } else { 34 | hasher.update(value.as_ref()); 35 | hasher.update(next_node.as_ref()); 36 | } 37 | value = hasher.finalize_reset().into(); 38 | } 39 | let root: [u8; 32] = root.as_ref().try_into().unwrap(); 40 | root == value 41 | } 42 | 43 | pub fn branch_from_bytes(s: &[[u8; 32]]) -> Vec { 44 | s.iter() 45 | .map(|hex| node_from_bytes(*hex)) 46 | .collect::>() 47 | } 48 | 49 | pub fn node_from_bytes(s: [u8; 32]) -> Node { 50 | Node::try_from(&s[..]).unwrap() 51 | } 52 | -------------------------------------------------------------------------------- /programs/ssz-withdrawals/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | 3 | mod beacon; 4 | mod proof; 5 | 6 | #[cfg(feature = "risc0")] 7 | extern crate sha2_risc0; 8 | 9 | #[cfg(feature = "sp1")] 10 | extern crate sha2_sp1; 11 | 12 | #[cfg(feature = "risc0")] 13 | risc0_zkvm::guest::entry!(main); 14 | 15 | #[cfg(feature = "sp1")] 16 | sp1_zkvm::entrypoint!(main); 17 | 18 | use beacon::hints; 19 | use beacon::node_from_bytes; 20 | use beacon::prove; 21 | use beacon::types::*; 22 | use hex_literal::hex; 23 | use ssz_rs::prelude::*; 24 | use std::collections::HashMap; 25 | 26 | /// Given a beacon block root, start slot, end slot, and eigenpod address, returns the sum of all 27 | /// beacon partial withdrawals in [start_slot, end_slot) to the given eigenpod address. 28 | pub fn main() { 29 | let beacon_block_root = node_from_bytes(hex!( 30 | "d00c4da1a3ad4d42bd35f128544227d19e163194569d69d54a3d14112e3c897c" 31 | )); 32 | let start_slot = 7855804; 33 | let end_slot = 7855807; 34 | let eigenpod_address = 35 | ExecutionAddress::try_from(hex!("e9cd1419a015dd05d47f6139f5b8e86b1e9e5cdd").to_vec()) 36 | .unwrap(); 37 | 38 | // Get slot number from block by proving the block header. 39 | let source_slot = prove::block_header(beacon_block_root).slot; 40 | 41 | // Load the witness data from outside of the vm. 42 | let (withdrawal_slots, validator_indexes) = 43 | hints::withdrawals_range(beacon_block_root, start_slot, end_slot, &eigenpod_address); 44 | 45 | // For all validator_indexes in the range, prove their withdrawable epoch so we can check 46 | // whether each withdrawal is partial or full. 47 | let validators_root = prove::validators_root(beacon_block_root); 48 | let mut withdrawable_epochs = HashMap::::new(); 49 | for validator_index in validator_indexes { 50 | println!("validator index: {}", validator_index); 51 | let validator = prove::validator(beacon_block_root, validators_root, validator_index); 52 | withdrawable_epochs.insert(validator_index, validator.withdrawable_epoch); 53 | } 54 | 55 | let mut sum = 0; 56 | 57 | // We only have 3 slots of withdrawal data in our test vector. In practice, users will want to prove a much larger range of withdrawals. 58 | // To simulate this, we loop over the withdrawal_slots 10 times to simulate more merkle proof verification to mirror realistic programs. 59 | for _ in 0..10 { 60 | for (slot, withdrawal_indexes) in &withdrawal_slots { 61 | println!("slot: {}", slot); 62 | let historical_block_root = 63 | prove::historical_block_root(beacon_block_root, source_slot, *slot); 64 | let withdrawals_root = prove::withdrawals_root(historical_block_root); 65 | let epoch = slot / 32; 66 | for index in withdrawal_indexes { 67 | let withdrawal = prove::withdrawal(historical_block_root, withdrawals_root, *index); 68 | 69 | let withdrawable_epoch = withdrawable_epochs 70 | .get(&withdrawal.validator_index) 71 | .unwrap(); 72 | if epoch < *withdrawable_epoch { 73 | sum += withdrawal.amount; 74 | } 75 | } 76 | } 77 | } 78 | 79 | println!("sum: {}", sum); 80 | } 81 | -------------------------------------------------------------------------------- /programs/ssz-withdrawals/src/proof.rs: -------------------------------------------------------------------------------- 1 | use alloy_primitives::U256; 2 | use ssz_rs::prelude::Node; 3 | use std::ops::Div; 4 | 5 | cfg_if::cfg_if! { 6 | if #[cfg(feature = "sp1")] { 7 | use sha2_sp1::{Digest, Sha256}; 8 | } else if #[cfg(feature = "risc0")] { 9 | use sha2_risc0::{Digest, Sha256}; 10 | } else { 11 | use sha2::{Digest, Sha256}; 12 | } 13 | } 14 | 15 | // From https://github.com/ralexstokes/ssz-rs/blob/main/ssz-rs/src/merkleization/proofs.rs 16 | // Modified to use alloy_primitives::U256 instead of u64 for large gindex values 17 | #[allow(dead_code, unused_variables)] 18 | pub fn is_valid_merkle_big_branch<'a>( 19 | leaf: &Node, 20 | mut branch: impl Iterator, 21 | depth: usize, 22 | index: U256, 23 | root: &Node, 24 | ) -> bool { 25 | let mut value: [u8; 32] = leaf.as_ref().try_into().unwrap(); 26 | let mut gindex = index; 27 | let mut hasher = Sha256::new(); 28 | let two = U256::from(2); 29 | for _ in 0..depth { 30 | let next_node = match branch.next() { 31 | Some(node) => node, 32 | None => return false, 33 | }; 34 | if gindex.bit(0) { 35 | hasher.update(next_node.as_ref()); 36 | hasher.update(value.as_ref()); 37 | } else { 38 | hasher.update(value.as_ref()); 39 | hasher.update(next_node.as_ref()); 40 | } 41 | gindex = gindex.div(two); 42 | value = hasher.finalize_reset().into(); 43 | } 44 | let root: [u8; 32] = root.as_ref().try_into().unwrap(); 45 | root == value 46 | } 47 | -------------------------------------------------------------------------------- /programs/tendermint-risc0/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | [package] 3 | version = "0.1.0" 4 | name = "tendermint-risc0" 5 | edition = "2021" 6 | 7 | [dependencies] 8 | risc0-zkvm = { version = "=1.2.1", default-features = false, features = ["std", "unstable"] } 9 | serde_json = { version = "1.0", default-features = false, features = ["alloc"] } 10 | serde = { version = "1.0", default-features = false, features = ["derive"] } 11 | tendermint = { version = "0.34.0", default-features = false } 12 | tendermint-light-client-verifier = { version = "0.34.0", default-features = false, features = [ 13 | "rust-crypto", 14 | ] } 15 | 16 | [patch.crates-io] 17 | sha2 = { git = "https://github.com/risc0/RustCrypto-hashes", tag = "sha2-v0.10.8-risczero.0" } 18 | ed25519-dalek = { git = "https://github.com/risc0/curve25519-dalek", tag = "curve25519-4.1.0-risczero.0" } 19 | tiny-keccak = { git = "https://github.com/risc0/tiny-keccak", tag = "tiny-keccak/v2.0.2-risczero.0" } 20 | k256 = { git = "https://github.com/risc0/RustCrypto-elliptic-curves", tag = "k256/v0.13.4-risczero.1" } 21 | p256 = { git = "https://github.com/risc0/RustCrypto-elliptic-curves", tag = "p256/v0.13.2-risczero.0" } 22 | rsa = { git = "https://github.com/risc0/RustCrypto-RSA", tag = "v0.9.6-risczero.0" } 23 | crypto-bigint = { git = "https://github.com/risc0/RustCrypto-crypto-bigint", tag = "v0.5.5-risczero.0" } 24 | ed25519-consensus = { git = "https://github.com/risc0/ed25519-consensus", rev = "8a6d26d1fcd377f9322ba83d3732d04c157e4778" } 25 | 26 | [features] 27 | risc0 = [] 28 | -------------------------------------------------------------------------------- /programs/tendermint-risc0/src/fixtures/small-1/next_validators.json: -------------------------------------------------------------------------------- 1 | { 2 | "jsonrpc": "2.0", 3 | "id": -1, 4 | "result": { 5 | "block_height": "6", 6 | "validators": [ 7 | { 8 | "address": "7619BFC85B72E319BF414A784D4DE40EE9B92C16", 9 | "pub_key": { 10 | "type": "tendermint/PubKeyEd25519", 11 | "value": "l/qNaf4JDxnhP+6Pf+2OSAJYksSIkjyefYCDvZPoahA=" 12 | }, 13 | "voting_power": "20000000", 14 | "proposer_priority": "0" 15 | } 16 | ], 17 | "count": "1", 18 | "total": "1" 19 | } 20 | } -------------------------------------------------------------------------------- /programs/tendermint-risc0/src/fixtures/small-1/signed_header.json: -------------------------------------------------------------------------------- 1 | { 2 | "jsonrpc": "2.0", 3 | "id": -1, 4 | "result": { 5 | "signed_header": { 6 | "header": { 7 | "version": { 8 | "block": "11", 9 | "app": "1" 10 | }, 11 | "chain_id": "mocha-4", 12 | "height": "5", 13 | "time": "2023-09-06T04:55:46.17235145Z", 14 | "last_block_id": { 15 | "hash": "7AF4A485BC82ECFD17101F0806EFE400E0579485621558561FB7905C80942620", 16 | "parts": { 17 | "total": 1, 18 | "hash": "D05AA31F6F6DBFAE1F3AE94EB6E30A051C4FEE62AAACAF2AA8BBAAEB60AA897B" 19 | } 20 | }, 21 | "last_commit_hash": "FBBD710A0CC8C2FD4E6903A7501E07021A81F08493E7F01079B0FE947EFA6152", 22 | "data_hash": "3D96B7D238E7E0456F6AF8E7CDF0A67BD6CF9C2089ECB559C659DCAA1F880353", 23 | "validators_hash": "F2503B99B4525B920D13AA20C974C0536A5C30CCDD62F5B7F4F00D0D02921E08", 24 | "next_validators_hash": "F2503B99B4525B920D13AA20C974C0536A5C30CCDD62F5B7F4F00D0D02921E08", 25 | "consensus_hash": "C0B6A634B72AE9687EA53B6D277A73ABA1386BA3CFC6D0F26963602F7F6FFCD6", 26 | "app_hash": "09B67FE1A5BBB0FA0898CABA78546F2A2333B16B53EA07D1A8FAF457F7E53480", 27 | "last_results_hash": "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855", 28 | "evidence_hash": "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855", 29 | "proposer_address": "7619BFC85B72E319BF414A784D4DE40EE9B92C16" 30 | }, 31 | "commit": { 32 | "height": "5", 33 | "round": 0, 34 | "block_id": { 35 | "hash": "D947781E13F83F0DF257C34F5AC2CFF86C1E62713D079F9786EA37F4FBE119B5", 36 | "parts": { 37 | "total": 1, 38 | "hash": "85E8EC8E136D753C9D980D07C68F56845FCFE8644A931D5499B779C17D8D9953" 39 | } 40 | }, 41 | "signatures": [ 42 | { 43 | "block_id_flag": 2, 44 | "validator_address": "7619BFC85B72E319BF414A784D4DE40EE9B92C16", 45 | "timestamp": "2023-09-06T04:55:57.209067617Z", 46 | "signature": "EPuSTGftCv6I+uMe/5zCQWwjXMTMXnR/Nx+XMbTfmsYlqDctoleRSmn4t8TOpG6th13krC2PFpYm0hnM87lfBQ==" 47 | } 48 | ] 49 | } 50 | }, 51 | "canonical": true 52 | } 53 | } -------------------------------------------------------------------------------- /programs/tendermint-risc0/src/fixtures/small-1/validators.json: -------------------------------------------------------------------------------- 1 | { 2 | "jsonrpc": "2.0", 3 | "id": -1, 4 | "result": { 5 | "block_height": "5", 6 | "validators": [ 7 | { 8 | "address": "7619BFC85B72E319BF414A784D4DE40EE9B92C16", 9 | "pub_key": { 10 | "type": "tendermint/PubKeyEd25519", 11 | "value": "l/qNaf4JDxnhP+6Pf+2OSAJYksSIkjyefYCDvZPoahA=" 12 | }, 13 | "voting_power": "20000000", 14 | "proposer_priority": "0" 15 | } 16 | ], 17 | "count": "1", 18 | "total": "1" 19 | } 20 | } -------------------------------------------------------------------------------- /programs/tendermint-risc0/src/fixtures/small-2/next_validators.json: -------------------------------------------------------------------------------- 1 | { 2 | "jsonrpc": "2.0", 3 | "id": -1, 4 | "result": { 5 | "block_height": "11", 6 | "validators": [ 7 | { 8 | "address": "7619BFC85B72E319BF414A784D4DE40EE9B92C16", 9 | "pub_key": { 10 | "type": "tendermint/PubKeyEd25519", 11 | "value": "l/qNaf4JDxnhP+6Pf+2OSAJYksSIkjyefYCDvZPoahA=" 12 | }, 13 | "voting_power": "20000000", 14 | "proposer_priority": "0" 15 | } 16 | ], 17 | "count": "1", 18 | "total": "1" 19 | } 20 | } -------------------------------------------------------------------------------- /programs/tendermint-risc0/src/fixtures/small-2/signed_header.json: -------------------------------------------------------------------------------- 1 | { 2 | "jsonrpc": "2.0", 3 | "id": -1, 4 | "result": { 5 | "signed_header": { 6 | "header": { 7 | "version": { 8 | "block": "11", 9 | "app": "1" 10 | }, 11 | "chain_id": "mocha-4", 12 | "height": "10", 13 | "time": "2023-09-06T04:56:41.367027518Z", 14 | "last_block_id": { 15 | "hash": "5C5451567973D8658A607D58F035BA9078291E33D880A0E6E67145C717E6B11B", 16 | "parts": { 17 | "total": 1, 18 | "hash": "2F0BDE430A67FE332F4264C2B47955218671DA9CAE5429066EA72762212DC691" 19 | } 20 | }, 21 | "last_commit_hash": "F252880F385C34E371813904E164A0FD6929F34159E5322262B07A593B8D8CB4", 22 | "data_hash": "3D96B7D238E7E0456F6AF8E7CDF0A67BD6CF9C2089ECB559C659DCAA1F880353", 23 | "validators_hash": "F2503B99B4525B920D13AA20C974C0536A5C30CCDD62F5B7F4F00D0D02921E08", 24 | "next_validators_hash": "F2503B99B4525B920D13AA20C974C0536A5C30CCDD62F5B7F4F00D0D02921E08", 25 | "consensus_hash": "C0B6A634B72AE9687EA53B6D277A73ABA1386BA3CFC6D0F26963602F7F6FFCD6", 26 | "app_hash": "AEFDA90AD09ACCFE5BC708D322C0D53E38DD54388E2AD970D09672DD301F4F66", 27 | "last_results_hash": "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855", 28 | "evidence_hash": "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855", 29 | "proposer_address": "7619BFC85B72E319BF414A784D4DE40EE9B92C16" 30 | }, 31 | "commit": { 32 | "height": "10", 33 | "round": 0, 34 | "block_id": { 35 | "hash": "D31ED2873DF9678AA8E635789BE45098DD8631F04970E29AAF1EA903BBECA710", 36 | "parts": { 37 | "total": 1, 38 | "hash": "8553C43FBFFA473D592D38816410B2A2371D23544D2F43E3611EDB916A504F64" 39 | } 40 | }, 41 | "signatures": [ 42 | { 43 | "block_id_flag": 2, 44 | "validator_address": "7619BFC85B72E319BF414A784D4DE40EE9B92C16", 45 | "timestamp": "2023-09-06T04:56:52.396961682Z", 46 | "signature": "4ZI6OBtSWcHcJDOII1xKTgqNKlThikXVNOk4qgaMchj7bRQMyDCcBRdPZFrF/YNNnLxiOiP9jnJh+QpccSX5Ag==" 47 | } 48 | ] 49 | } 50 | }, 51 | "canonical": true 52 | } 53 | } -------------------------------------------------------------------------------- /programs/tendermint-risc0/src/fixtures/small-2/validators.json: -------------------------------------------------------------------------------- 1 | { 2 | "jsonrpc": "2.0", 3 | "id": -1, 4 | "result": { 5 | "block_height": "10", 6 | "validators": [ 7 | { 8 | "address": "7619BFC85B72E319BF414A784D4DE40EE9B92C16", 9 | "pub_key": { 10 | "type": "tendermint/PubKeyEd25519", 11 | "value": "l/qNaf4JDxnhP+6Pf+2OSAJYksSIkjyefYCDvZPoahA=" 12 | }, 13 | "voting_power": "20000000", 14 | "proposer_priority": "0" 15 | } 16 | ], 17 | "count": "1", 18 | "total": "1" 19 | } 20 | } -------------------------------------------------------------------------------- /programs/tendermint-risc0/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | 3 | use core::time::Duration; 4 | use serde::Deserialize; 5 | use tendermint::{node::Id, validator::Info}; 6 | use tendermint_light_client_verifier::{ 7 | options::Options, 8 | types::{LightBlock, SignedHeader, ValidatorSet}, 9 | ProdVerifier, Verdict, Verifier, 10 | }; 11 | 12 | #[derive(Debug, Deserialize)] 13 | pub struct CommitResponse { 14 | pub result: SignedHeaderWrapper, 15 | } 16 | 17 | #[derive(Debug, Deserialize)] 18 | pub struct SignedHeaderWrapper { 19 | pub signed_header: SignedHeader, 20 | } 21 | 22 | #[derive(Debug, Deserialize)] 23 | pub struct ValidatorSetResponse { 24 | pub result: BlockValidatorSet, 25 | } 26 | 27 | #[derive(Debug, Deserialize)] 28 | pub struct BlockValidatorSet { 29 | pub block_height: String, 30 | pub validators: Vec, 31 | pub count: String, 32 | pub total: String, 33 | } 34 | 35 | risc0_zkvm::guest::entry!(main); 36 | 37 | pub fn main() { 38 | let peer_id: [u8; 20] = [ 39 | 0x72, 0x6b, 0xc8, 0xd2, 0x60, 0x38, 0x7c, 0xf5, 0x6e, 0xcf, 0xad, 0x3a, 0x6b, 0xf6, 0xfe, 40 | 0xcd, 0x90, 0x3e, 0x18, 0xa2, 41 | ]; 42 | // Generate the Light Block's without testgen 43 | let file_content = include_bytes!("./fixtures/1/signed_header.json"); 44 | let file_content_str = 45 | core::str::from_utf8(file_content).expect("Failed to convert file content to string"); 46 | 47 | let commit_response: CommitResponse = 48 | serde_json::from_str(file_content_str).expect("Failed to parse JSON"); 49 | let signed_header = commit_response.result.signed_header; 50 | 51 | let file_content = include_bytes!("./fixtures/1/validators.json"); 52 | let file_content_str = 53 | core::str::from_utf8(file_content).expect("Failed to convert file content to string"); 54 | let validators_response: ValidatorSetResponse = 55 | serde_json::from_str(file_content_str).expect("Failed to parse JSON"); 56 | let validators = validators_response.result; 57 | let validators = ValidatorSet::new(validators.validators, None); 58 | 59 | let file_content = include_bytes!("./fixtures/1/next_validators.json"); 60 | let file_content_str = 61 | core::str::from_utf8(file_content).expect("Failed to convert file content to string"); 62 | let next_validators_response: ValidatorSetResponse = 63 | serde_json::from_str(file_content_str).expect("Failed to parse JSON"); 64 | let next_validators = next_validators_response.result; 65 | let next_validators = ValidatorSet::new(next_validators.validators, None); 66 | 67 | // Create a default light block with a valid chain-id for height `1` with a timestamp 20 68 | // secs before now (to be treated as trusted state) 69 | let light_block_1: LightBlock = 70 | LightBlock::new(signed_header, validators, next_validators, Id::new(peer_id)); 71 | 72 | // // Generate the Light Block's without testgen 73 | let file_content = include_bytes!("./fixtures/2/signed_header.json"); 74 | let file_content_str = 75 | core::str::from_utf8(file_content).expect("Failed to convert file content to string"); 76 | 77 | let commit_response: CommitResponse = 78 | serde_json::from_str(file_content_str).expect("Failed to parse JSON"); 79 | let signed_header = commit_response.result.signed_header; 80 | 81 | let file_content = include_bytes!("./fixtures/2/validators.json"); 82 | let file_content_str = 83 | core::str::from_utf8(file_content).expect("Failed to convert file content to string"); 84 | let validators_response: ValidatorSetResponse = 85 | serde_json::from_str(file_content_str).expect("Failed to parse JSON"); 86 | let validators = validators_response.result; 87 | let validators = ValidatorSet::new(validators.validators, None); 88 | 89 | let file_content = include_bytes!("./fixtures/2/next_validators.json"); 90 | let file_content_str = 91 | core::str::from_utf8(file_content).expect("Failed to convert file content to string"); 92 | let next_validators_response: ValidatorSetResponse = 93 | serde_json::from_str(file_content_str).expect("Failed to parse JSON"); 94 | let next_validators = next_validators_response.result; 95 | let next_validators = ValidatorSet::new(next_validators.validators, None); 96 | 97 | // Create a default light block with a valid chain-id for height `1` with a timestamp 20 98 | // secs before now (to be treated as trusted state) 99 | let light_block_2: LightBlock = 100 | LightBlock::new(signed_header, validators, next_validators, Id::new(peer_id)); 101 | 102 | let vp = ProdVerifier::default(); 103 | let opt = Options { 104 | trust_threshold: Default::default(), 105 | trusting_period: Duration::from_secs(500), 106 | clock_drift: Default::default(), 107 | }; 108 | 109 | let verify_time = light_block_2.time() + Duration::from_secs(20); 110 | 111 | let verdict = vp.verify_update_header( 112 | light_block_2.as_untrusted_state(), 113 | light_block_1.as_trusted_state(), 114 | &opt, 115 | verify_time.unwrap(), 116 | ); 117 | 118 | match verdict { 119 | Verdict::Success => { 120 | println!("success"); 121 | } 122 | v => panic!("expected success, got: {:?}", v), 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /programs/tendermint-sp1/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | [package] 3 | version = "0.1.0" 4 | name = "tendermint-sp1" 5 | edition = "2021" 6 | 7 | [dependencies] 8 | sp1-zkvm = "4.0.0-rc.10" 9 | 10 | serde = { version = "1.0.204", default-features = false, features = ["derive"] } 11 | serde_json = { version = "1.0", default-features = false, features = ["alloc"] } 12 | tendermint = { version = "=0.40.1", default-features = false } 13 | tendermint-light-client-verifier = { version = "=0.40.1", default-features = false, features = [ 14 | "rust-crypto", 15 | ] } 16 | 17 | [patch.crates-io] 18 | sha2 = { git = "https://github.com/sp1-patches/RustCrypto-hashes", package = "sha2", tag = "patch-sha2-0.10.8-sp1-4.0.0-rc.3" } 19 | curve25519-dalek-ng = { git = "https://github.com/sp1-patches/curve25519-dalek-ng", tag = "patch-4.1.1-sp1-4.0.0-rc.3" } 20 | 21 | [features] 22 | sp1 = [] 23 | -------------------------------------------------------------------------------- /programs/tendermint-sp1/src/fixtures/small-1/next_validators.json: -------------------------------------------------------------------------------- 1 | { 2 | "jsonrpc": "2.0", 3 | "id": -1, 4 | "result": { 5 | "block_height": "6", 6 | "validators": [ 7 | { 8 | "address": "7619BFC85B72E319BF414A784D4DE40EE9B92C16", 9 | "pub_key": { 10 | "type": "tendermint/PubKeyEd25519", 11 | "value": "l/qNaf4JDxnhP+6Pf+2OSAJYksSIkjyefYCDvZPoahA=" 12 | }, 13 | "voting_power": "20000000", 14 | "proposer_priority": "0" 15 | } 16 | ], 17 | "count": "1", 18 | "total": "1" 19 | } 20 | } -------------------------------------------------------------------------------- /programs/tendermint-sp1/src/fixtures/small-1/signed_header.json: -------------------------------------------------------------------------------- 1 | { 2 | "jsonrpc": "2.0", 3 | "id": -1, 4 | "result": { 5 | "signed_header": { 6 | "header": { 7 | "version": { 8 | "block": "11", 9 | "app": "1" 10 | }, 11 | "chain_id": "mocha-4", 12 | "height": "5", 13 | "time": "2023-09-06T04:55:46.17235145Z", 14 | "last_block_id": { 15 | "hash": "7AF4A485BC82ECFD17101F0806EFE400E0579485621558561FB7905C80942620", 16 | "parts": { 17 | "total": 1, 18 | "hash": "D05AA31F6F6DBFAE1F3AE94EB6E30A051C4FEE62AAACAF2AA8BBAAEB60AA897B" 19 | } 20 | }, 21 | "last_commit_hash": "FBBD710A0CC8C2FD4E6903A7501E07021A81F08493E7F01079B0FE947EFA6152", 22 | "data_hash": "3D96B7D238E7E0456F6AF8E7CDF0A67BD6CF9C2089ECB559C659DCAA1F880353", 23 | "validators_hash": "F2503B99B4525B920D13AA20C974C0536A5C30CCDD62F5B7F4F00D0D02921E08", 24 | "next_validators_hash": "F2503B99B4525B920D13AA20C974C0536A5C30CCDD62F5B7F4F00D0D02921E08", 25 | "consensus_hash": "C0B6A634B72AE9687EA53B6D277A73ABA1386BA3CFC6D0F26963602F7F6FFCD6", 26 | "app_hash": "09B67FE1A5BBB0FA0898CABA78546F2A2333B16B53EA07D1A8FAF457F7E53480", 27 | "last_results_hash": "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855", 28 | "evidence_hash": "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855", 29 | "proposer_address": "7619BFC85B72E319BF414A784D4DE40EE9B92C16" 30 | }, 31 | "commit": { 32 | "height": "5", 33 | "round": 0, 34 | "block_id": { 35 | "hash": "D947781E13F83F0DF257C34F5AC2CFF86C1E62713D079F9786EA37F4FBE119B5", 36 | "parts": { 37 | "total": 1, 38 | "hash": "85E8EC8E136D753C9D980D07C68F56845FCFE8644A931D5499B779C17D8D9953" 39 | } 40 | }, 41 | "signatures": [ 42 | { 43 | "block_id_flag": 2, 44 | "validator_address": "7619BFC85B72E319BF414A784D4DE40EE9B92C16", 45 | "timestamp": "2023-09-06T04:55:57.209067617Z", 46 | "signature": "EPuSTGftCv6I+uMe/5zCQWwjXMTMXnR/Nx+XMbTfmsYlqDctoleRSmn4t8TOpG6th13krC2PFpYm0hnM87lfBQ==" 47 | } 48 | ] 49 | } 50 | }, 51 | "canonical": true 52 | } 53 | } -------------------------------------------------------------------------------- /programs/tendermint-sp1/src/fixtures/small-1/validators.json: -------------------------------------------------------------------------------- 1 | { 2 | "jsonrpc": "2.0", 3 | "id": -1, 4 | "result": { 5 | "block_height": "5", 6 | "validators": [ 7 | { 8 | "address": "7619BFC85B72E319BF414A784D4DE40EE9B92C16", 9 | "pub_key": { 10 | "type": "tendermint/PubKeyEd25519", 11 | "value": "l/qNaf4JDxnhP+6Pf+2OSAJYksSIkjyefYCDvZPoahA=" 12 | }, 13 | "voting_power": "20000000", 14 | "proposer_priority": "0" 15 | } 16 | ], 17 | "count": "1", 18 | "total": "1" 19 | } 20 | } -------------------------------------------------------------------------------- /programs/tendermint-sp1/src/fixtures/small-2/next_validators.json: -------------------------------------------------------------------------------- 1 | { 2 | "jsonrpc": "2.0", 3 | "id": -1, 4 | "result": { 5 | "block_height": "11", 6 | "validators": [ 7 | { 8 | "address": "7619BFC85B72E319BF414A784D4DE40EE9B92C16", 9 | "pub_key": { 10 | "type": "tendermint/PubKeyEd25519", 11 | "value": "l/qNaf4JDxnhP+6Pf+2OSAJYksSIkjyefYCDvZPoahA=" 12 | }, 13 | "voting_power": "20000000", 14 | "proposer_priority": "0" 15 | } 16 | ], 17 | "count": "1", 18 | "total": "1" 19 | } 20 | } -------------------------------------------------------------------------------- /programs/tendermint-sp1/src/fixtures/small-2/signed_header.json: -------------------------------------------------------------------------------- 1 | { 2 | "jsonrpc": "2.0", 3 | "id": -1, 4 | "result": { 5 | "signed_header": { 6 | "header": { 7 | "version": { 8 | "block": "11", 9 | "app": "1" 10 | }, 11 | "chain_id": "mocha-4", 12 | "height": "10", 13 | "time": "2023-09-06T04:56:41.367027518Z", 14 | "last_block_id": { 15 | "hash": "5C5451567973D8658A607D58F035BA9078291E33D880A0E6E67145C717E6B11B", 16 | "parts": { 17 | "total": 1, 18 | "hash": "2F0BDE430A67FE332F4264C2B47955218671DA9CAE5429066EA72762212DC691" 19 | } 20 | }, 21 | "last_commit_hash": "F252880F385C34E371813904E164A0FD6929F34159E5322262B07A593B8D8CB4", 22 | "data_hash": "3D96B7D238E7E0456F6AF8E7CDF0A67BD6CF9C2089ECB559C659DCAA1F880353", 23 | "validators_hash": "F2503B99B4525B920D13AA20C974C0536A5C30CCDD62F5B7F4F00D0D02921E08", 24 | "next_validators_hash": "F2503B99B4525B920D13AA20C974C0536A5C30CCDD62F5B7F4F00D0D02921E08", 25 | "consensus_hash": "C0B6A634B72AE9687EA53B6D277A73ABA1386BA3CFC6D0F26963602F7F6FFCD6", 26 | "app_hash": "AEFDA90AD09ACCFE5BC708D322C0D53E38DD54388E2AD970D09672DD301F4F66", 27 | "last_results_hash": "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855", 28 | "evidence_hash": "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855", 29 | "proposer_address": "7619BFC85B72E319BF414A784D4DE40EE9B92C16" 30 | }, 31 | "commit": { 32 | "height": "10", 33 | "round": 0, 34 | "block_id": { 35 | "hash": "D31ED2873DF9678AA8E635789BE45098DD8631F04970E29AAF1EA903BBECA710", 36 | "parts": { 37 | "total": 1, 38 | "hash": "8553C43FBFFA473D592D38816410B2A2371D23544D2F43E3611EDB916A504F64" 39 | } 40 | }, 41 | "signatures": [ 42 | { 43 | "block_id_flag": 2, 44 | "validator_address": "7619BFC85B72E319BF414A784D4DE40EE9B92C16", 45 | "timestamp": "2023-09-06T04:56:52.396961682Z", 46 | "signature": "4ZI6OBtSWcHcJDOII1xKTgqNKlThikXVNOk4qgaMchj7bRQMyDCcBRdPZFrF/YNNnLxiOiP9jnJh+QpccSX5Ag==" 47 | } 48 | ] 49 | } 50 | }, 51 | "canonical": true 52 | } 53 | } -------------------------------------------------------------------------------- /programs/tendermint-sp1/src/fixtures/small-2/validators.json: -------------------------------------------------------------------------------- 1 | { 2 | "jsonrpc": "2.0", 3 | "id": -1, 4 | "result": { 5 | "block_height": "10", 6 | "validators": [ 7 | { 8 | "address": "7619BFC85B72E319BF414A784D4DE40EE9B92C16", 9 | "pub_key": { 10 | "type": "tendermint/PubKeyEd25519", 11 | "value": "l/qNaf4JDxnhP+6Pf+2OSAJYksSIkjyefYCDvZPoahA=" 12 | }, 13 | "voting_power": "20000000", 14 | "proposer_priority": "0" 15 | } 16 | ], 17 | "count": "1", 18 | "total": "1" 19 | } 20 | } -------------------------------------------------------------------------------- /programs/tendermint-sp1/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | 3 | use core::time::Duration; 4 | use serde::Deserialize; 5 | use tendermint::{node::Id, validator::Info}; 6 | use tendermint_light_client_verifier::{ 7 | options::Options, 8 | types::{LightBlock, SignedHeader, ValidatorSet}, 9 | ProdVerifier, Verdict, Verifier, 10 | }; 11 | 12 | #[derive(Debug, Deserialize)] 13 | pub struct CommitResponse { 14 | pub result: SignedHeaderWrapper, 15 | } 16 | 17 | #[derive(Debug, Deserialize)] 18 | pub struct SignedHeaderWrapper { 19 | pub signed_header: SignedHeader, 20 | } 21 | 22 | #[derive(Debug, Deserialize)] 23 | pub struct ValidatorSetResponse { 24 | pub result: BlockValidatorSet, 25 | } 26 | 27 | #[derive(Debug, Deserialize)] 28 | pub struct BlockValidatorSet { 29 | pub block_height: String, 30 | pub validators: Vec, 31 | pub count: String, 32 | pub total: String, 33 | } 34 | 35 | sp1_zkvm::entrypoint!(main); 36 | 37 | pub fn main() { 38 | let peer_id: [u8; 20] = [ 39 | 0x72, 0x6b, 0xc8, 0xd2, 0x60, 0x38, 0x7c, 0xf5, 0x6e, 0xcf, 0xad, 0x3a, 0x6b, 0xf6, 0xfe, 40 | 0xcd, 0x90, 0x3e, 0x18, 0xa2, 41 | ]; 42 | // Generate the Light Block's without testgen 43 | let file_content = include_bytes!("./fixtures/1/signed_header.json"); 44 | let file_content_str = 45 | core::str::from_utf8(file_content).expect("Failed to convert file content to string"); 46 | 47 | let commit_response: CommitResponse = 48 | serde_json::from_str(file_content_str).expect("Failed to parse JSON"); 49 | let signed_header = commit_response.result.signed_header; 50 | 51 | let file_content = include_bytes!("./fixtures/1/validators.json"); 52 | let file_content_str = 53 | core::str::from_utf8(file_content).expect("Failed to convert file content to string"); 54 | let validators_response: ValidatorSetResponse = 55 | serde_json::from_str(file_content_str).expect("Failed to parse JSON"); 56 | let validators = validators_response.result; 57 | let validators = ValidatorSet::new(validators.validators, None); 58 | 59 | let file_content = include_bytes!("./fixtures/1/next_validators.json"); 60 | let file_content_str = 61 | core::str::from_utf8(file_content).expect("Failed to convert file content to string"); 62 | let next_validators_response: ValidatorSetResponse = 63 | serde_json::from_str(file_content_str).expect("Failed to parse JSON"); 64 | let next_validators = next_validators_response.result; 65 | let next_validators = ValidatorSet::new(next_validators.validators, None); 66 | 67 | // Create a default light block with a valid chain-id for height `1` with a timestamp 20 68 | // secs before now (to be treated as trusted state) 69 | let light_block_1: LightBlock = 70 | LightBlock::new(signed_header, validators, next_validators, Id::new(peer_id)); 71 | 72 | // // Generate the Light Block's without testgen 73 | let file_content = include_bytes!("./fixtures/2/signed_header.json"); 74 | let file_content_str = 75 | core::str::from_utf8(file_content).expect("Failed to convert file content to string"); 76 | 77 | let commit_response: CommitResponse = 78 | serde_json::from_str(file_content_str).expect("Failed to parse JSON"); 79 | let signed_header = commit_response.result.signed_header; 80 | 81 | let file_content = include_bytes!("./fixtures/2/validators.json"); 82 | let file_content_str = 83 | core::str::from_utf8(file_content).expect("Failed to convert file content to string"); 84 | let validators_response: ValidatorSetResponse = 85 | serde_json::from_str(file_content_str).expect("Failed to parse JSON"); 86 | let validators = validators_response.result; 87 | let validators = ValidatorSet::new(validators.validators, None); 88 | 89 | let file_content = include_bytes!("./fixtures/2/next_validators.json"); 90 | let file_content_str = 91 | core::str::from_utf8(file_content).expect("Failed to convert file content to string"); 92 | let next_validators_response: ValidatorSetResponse = 93 | serde_json::from_str(file_content_str).expect("Failed to parse JSON"); 94 | let next_validators = next_validators_response.result; 95 | let next_validators = ValidatorSet::new(next_validators.validators, None); 96 | 97 | // Create a default light block with a valid chain-id for height `1` with a timestamp 20 98 | // secs before now (to be treated as trusted state) 99 | let light_block_2: LightBlock = 100 | LightBlock::new(signed_header, validators, next_validators, Id::new(peer_id)); 101 | 102 | let vp = ProdVerifier::default(); 103 | let opt = Options { 104 | trust_threshold: Default::default(), 105 | trusting_period: Duration::from_secs(500), 106 | clock_drift: Default::default(), 107 | }; 108 | 109 | let verify_time = light_block_2.time() + Duration::from_secs(20); 110 | 111 | let verdict = vp.verify_update_header( 112 | light_block_2.as_untrusted_state(), 113 | light_block_1.as_trusted_state(), 114 | &opt, 115 | verify_time.unwrap(), 116 | ); 117 | 118 | match verdict { 119 | Verdict::Success => { 120 | println!("success"); 121 | } 122 | v => panic!("expected success, got: {:?}", v), 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /programs/zk-email-risc0/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | [package] 3 | name = "zk-email-risc0" 4 | version = "0.1.0" 5 | edition = "2021" 6 | 7 | [dependencies] 8 | base64 = "0.22.1" 9 | rsa = { version = "=0.9.6", optional = true } 10 | sp1-rsa = { package = "rsa", git = "https://github.com/sp1-patches/RustCrypto-RSA", branch = "n/prep-4.0.0", optional = true } 11 | serde = "1.0.200" 12 | sp1-zkvm = "4.0.0-rc.10" 13 | sha2-sp1 = { git = "https://github.com/sp1-patches/RustCrypto-hashes", package = "sha2", tag = "patch-sha2-0.10.8-sp1-4.0.0-rc.3", optional = true } 14 | sha2-risc0 = { git = "https://github.com/risc0/RustCrypto-hashes", package = "sha2", tag = "sha2-v0.10.6-risczero.0", optional = true } 15 | risc0-zkvm = { version = "=1.2.1", default-features = false, features = ["std", "unstable"], optional = true } 16 | 17 | [features] 18 | risc0 = ["dep:rsa", "dep:sha2-risc0", "dep:risc0-zkvm"] 19 | sp1 = ["dep:sp1-rsa", "dep:sha2-sp1"] 20 | 21 | [patch.crates-io] 22 | rsa = { git = "https://github.com/risc0/RustCrypto-RSA", tag = "v0.9.6-risczero.0" } -------------------------------------------------------------------------------- /programs/zk-email-risc0/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | 3 | #[cfg(feature = "sp1")] 4 | sp1_zkvm::entrypoint!(main); 5 | 6 | #[cfg(feature = "risc0")] 7 | risc0_zkvm::guest::entry!(main); 8 | 9 | use std::str::FromStr; 10 | 11 | use base64::prelude::*; 12 | 13 | #[cfg(feature = "risc0")] 14 | use rsa::{BigUint, Pkcs1v15Sign, RsaPublicKey}; 15 | #[cfg(feature = "sp1")] 16 | use sp1_rsa::{BigUint, Pkcs1v15Sign, RsaPublicKey}; 17 | 18 | use serde::{Deserialize, Serialize}; 19 | 20 | #[cfg(feature = "risc0")] 21 | use sha2_risc0::{Digest, Sha256}; 22 | 23 | #[cfg(feature = "sp1")] 24 | use sha2_sp1::{Digest, Sha256}; 25 | 26 | #[derive(Serialize, Deserialize, Debug, Clone)] 27 | struct EmailInputs { 28 | public_key: String, 29 | signature: String, 30 | headers: String, 31 | body: String, 32 | body_hash: String, 33 | } 34 | 35 | pub fn main() { 36 | #[cfg(feature = "sp1")] 37 | let email_inputs: EmailInputs = sp1_zkvm::io::read(); 38 | 39 | #[cfg(feature = "risc0")] 40 | let email_inputs: EmailInputs = risc0_zkvm::guest::env::read(); 41 | 42 | let signature_verified = verify_signature(&email_inputs); 43 | let body_verified = verify_body(&email_inputs); 44 | 45 | #[cfg(feature = "sp1")] 46 | { 47 | sp1_zkvm::io::commit(&signature_verified); 48 | sp1_zkvm::io::commit(&body_verified); 49 | } 50 | 51 | #[cfg(feature = "risc0")] 52 | { 53 | risc0_zkvm::guest::env::commit(&signature_verified); 54 | risc0_zkvm::guest::env::commit(&body_verified); 55 | } 56 | } 57 | 58 | fn verify_body(email_inputs: &EmailInputs) -> bool { 59 | // get sha256 hash of body 60 | let mut hasher = Sha256::new(); 61 | hasher.update(email_inputs.body.as_bytes()); 62 | let hash = hasher.finalize(); 63 | 64 | // encode hash to base64 65 | let base64_hash = BASE64_STANDARD.encode(hash); 66 | 67 | // compare computed body hash with signed body hash & print if fails 68 | base64_hash == email_inputs.body_hash 69 | } 70 | 71 | fn verify_signature(email_inputs: &EmailInputs) -> bool { 72 | // signature scheme: rsa-sha256 73 | // 1. get sha256 hash of header 74 | let mut hasher = Sha256::new(); 75 | hasher.update(email_inputs.headers.as_bytes()); 76 | let hash = hasher.finalize(); 77 | 78 | // 2. decode the public key from PEM format 79 | let public_key = RsaPublicKey::new( 80 | BigUint::from_bytes_be(&BASE64_STANDARD.decode(&email_inputs.public_key).unwrap()), 81 | // BigUint::from_str(&email_inputs.public_key).unwrap(), 82 | BigUint::from(65537u64), 83 | ) 84 | .expect("error decoding public key into PEM format"); 85 | 86 | // 3. decode the signature from base64 into binary 87 | let signature = BASE64_STANDARD 88 | .decode(&email_inputs.signature) 89 | .expect("error decoding signature into binary"); 90 | 91 | // 4. verify the signature 92 | // RSASSA-PKCS1-V1_5 magic padding bytes 93 | // https://crypto.stackexchange.com/questions/86385/initial-value-for-rsa-and-sha-256-signature-encoding 94 | let prefix: Box<[u8]> = Box::new([ 95 | 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 96 | 0x05, 0x00, 0x04, 0x20, 97 | ]); 98 | // SHA-256 produces hash output of 32 bytes 99 | let hash_len = Some(32); 100 | let padding = Pkcs1v15Sign { hash_len, prefix }; 101 | let result = public_key.verify(padding, &hash, &signature); 102 | 103 | // Print if signature is invalid 104 | result.is_ok() 105 | } 106 | -------------------------------------------------------------------------------- /programs/zk-email-sp1/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | [package] 3 | name = "zk-email-sp1" 4 | version = "0.1.0" 5 | edition = "2021" 6 | 7 | [dependencies] 8 | base64 = "0.22.1" 9 | rsa = { version = "0.9.7", optional = true } 10 | sp1-rsa = { package = "rsa", git = "https://github.com/sp1-patches/RustCrypto-RSA", branch = "n/prep-4.0.0", optional = true } 11 | serde = "1.0.200" 12 | sp1-zkvm = "4.0.0-rc.10" 13 | sha2-sp1 = { git = "https://github.com/sp1-patches/RustCrypto-hashes", package = "sha2", tag = "patch-sha2-0.10.8-sp1-4.0.0-rc.3", optional = true } 14 | sha2-risc0 = { git = "https://github.com/risc0/RustCrypto-hashes", package = "sha2", tag = "sha2-v0.10.6-risczero.0", optional = true } 15 | risc0-zkvm = { version = "=1.2.1", default-features = false, features = ["std", "unstable"], optional = true } 16 | 17 | [features] 18 | risc0 = ["dep:rsa", "dep:sha2-risc0", "dep:risc0-zkvm"] 19 | sp1 = ["dep:sp1-rsa", "dep:sha2-sp1"] -------------------------------------------------------------------------------- /programs/zk-email-sp1/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | 3 | #[cfg(feature = "sp1")] 4 | sp1_zkvm::entrypoint!(main); 5 | 6 | #[cfg(feature = "risc0")] 7 | risc0_zkvm::guest::entry!(main); 8 | 9 | use std::str::FromStr; 10 | 11 | use base64::prelude::*; 12 | 13 | #[cfg(feature = "risc0")] 14 | use rsa::{BigUint, Pkcs1v15Sign, RsaPublicKey}; 15 | #[cfg(feature = "sp1")] 16 | use sp1_rsa::{BigUint, Pkcs1v15Sign, RsaPublicKey}; 17 | 18 | use serde::{Deserialize, Serialize}; 19 | 20 | #[cfg(feature = "risc0")] 21 | use sha2_risc0::{Digest, Sha256}; 22 | 23 | #[cfg(feature = "sp1")] 24 | use sha2_sp1::{Digest, Sha256}; 25 | 26 | #[derive(Serialize, Deserialize, Debug, Clone)] 27 | struct EmailInputs { 28 | public_key: String, 29 | signature: String, 30 | headers: String, 31 | body: String, 32 | body_hash: String, 33 | } 34 | 35 | pub fn main() { 36 | #[cfg(feature = "sp1")] 37 | let email_inputs: EmailInputs = sp1_zkvm::io::read(); 38 | 39 | #[cfg(feature = "risc0")] 40 | let email_inputs: EmailInputs = risc0_zkvm::guest::env::read(); 41 | 42 | let signature_verified = verify_signature(&email_inputs); 43 | let body_verified = verify_body(&email_inputs); 44 | 45 | #[cfg(feature = "sp1")] 46 | { 47 | sp1_zkvm::io::commit(&signature_verified); 48 | sp1_zkvm::io::commit(&body_verified); 49 | } 50 | 51 | #[cfg(feature = "risc0")] 52 | { 53 | risc0_zkvm::guest::env::commit(&signature_verified); 54 | risc0_zkvm::guest::env::commit(&body_verified); 55 | } 56 | } 57 | 58 | fn verify_body(email_inputs: &EmailInputs) -> bool { 59 | // get sha256 hash of body 60 | let mut hasher = Sha256::new(); 61 | hasher.update(email_inputs.body.as_bytes()); 62 | let hash = hasher.finalize(); 63 | 64 | // encode hash to base64 65 | let base64_hash = BASE64_STANDARD.encode(hash); 66 | 67 | // compare computed body hash with signed body hash & print if fails 68 | base64_hash == email_inputs.body_hash 69 | } 70 | 71 | fn verify_signature(email_inputs: &EmailInputs) -> bool { 72 | // signature scheme: rsa-sha256 73 | // 1. get sha256 hash of header 74 | let mut hasher = Sha256::new(); 75 | hasher.update(email_inputs.headers.as_bytes()); 76 | let hash = hasher.finalize(); 77 | 78 | // 2. decode the public key from PEM format 79 | let public_key = RsaPublicKey::new( 80 | BigUint::from_bytes_be(&BASE64_STANDARD.decode(&email_inputs.public_key).unwrap()), 81 | // BigUint::from_str(&email_inputs.public_key).unwrap(), 82 | BigUint::from(65537u64), 83 | ) 84 | .expect("error decoding public key into PEM format"); 85 | 86 | // 3. decode the signature from base64 into binary 87 | let signature = BASE64_STANDARD 88 | .decode(&email_inputs.signature) 89 | .expect("error decoding signature into binary"); 90 | 91 | // 4. verify the signature 92 | // RSASSA-PKCS1-V1_5 magic padding bytes 93 | // https://crypto.stackexchange.com/questions/86385/initial-value-for-rsa-and-sha-256-signature-encoding 94 | let prefix: Box<[u8]> = Box::new([ 95 | 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 96 | 0x05, 0x00, 0x04, 0x20, 97 | ]); 98 | // SHA-256 produces hash output of 32 bytes 99 | let hash_len = Some(32); 100 | let padding = Pkcs1v15Sign { hash_len, prefix }; 101 | let result = public_key.verify(padding, &hash, &signature); 102 | 103 | // Print if signature is invalid 104 | result.is_ok() 105 | } 106 | -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | reorder_imports = true 2 | imports_granularity = "Crate" 3 | use_small_heuristics = "Max" 4 | comment_width = 100 5 | wrap_comments = true 6 | binop_separator = "Back" 7 | trailing_comma = "Vertical" 8 | trailing_semicolon = false 9 | use_field_init_shorthand = true 10 | format_code_in_doc_comments = true 11 | doc_comment_code_block_width = 100 -------------------------------------------------------------------------------- /sweep.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import subprocess 3 | from itertools import product 4 | 5 | 6 | def run_benchmark( 7 | filename, trials, programs, provers, hashfns, shard_sizes, block_1, block_2 8 | ): 9 | option_combinations = product(provers, programs, hashfns, shard_sizes) 10 | for prover, program, hashfn, shard_size in option_combinations: 11 | first_shard_size = shard_sizes[0] 12 | if ( 13 | prover != "sp1" and shard_size != first_shard_size 14 | ): # Only sp1 supports different shard sizes 15 | continue 16 | print(f"Running: {program}, {prover}, {hashfn}, {shard_size}") 17 | for _ in range(trials): 18 | if program == "reth1": 19 | subprocess.run( 20 | [ 21 | "bash", 22 | "eval.sh", 23 | "reth", 24 | prover, 25 | hashfn, 26 | str(shard_size), 27 | filename, 28 | block_1, 29 | ] 30 | ) 31 | elif program == "reth2": 32 | subprocess.run( 33 | [ 34 | "bash", 35 | "eval.sh", 36 | "reth", 37 | prover, 38 | hashfn, 39 | str(shard_size), 40 | filename, 41 | block_2, 42 | ] 43 | ) 44 | else: 45 | if "groth16" in program: 46 | subprocess.run( 47 | [ 48 | "bash", 49 | "eval.sh", 50 | "fibonacci20k", 51 | prover, 52 | hashfn, 53 | str(shard_size), 54 | filename, 55 | "buildOnly", 56 | ] 57 | ) 58 | subprocess.run( 59 | [ 60 | "bash", 61 | "eval.sh", 62 | program, 63 | prover, 64 | hashfn, 65 | str(shard_size), 66 | filename, 67 | ] 68 | ) 69 | 70 | def main(): 71 | parser = argparse.ArgumentParser( 72 | description="Run benchmarks with various combinations of options." 73 | ) 74 | parser.add_argument( 75 | "--filename", default="benchmark", help="Filename for the benchmark" 76 | ) 77 | parser.add_argument("--trials", type=int, default=1, help="Number of trials to run") 78 | parser.add_argument( 79 | "--programs", 80 | nargs="+", 81 | default=[ 82 | "loop10k", 83 | "loop100k", 84 | "loop1m", 85 | "loop3m", 86 | "loop10m", 87 | "loop30m", 88 | "loop100m", 89 | "loop300m", 90 | "fibonacci20k", 91 | "fibonacci200k", 92 | "fibonacci2m", 93 | "fibonacci4m", 94 | "fibonacci20m", 95 | "fibonacci40m", 96 | "fibonacci200m", 97 | "fibonacci400m", 98 | "fibonacci1b", 99 | "fibonacci2b", 100 | "fibonacci4b", 101 | "sha256100kb", 102 | "sha256300kb", 103 | "sha2561mb", 104 | "sha2563mb", 105 | "sha25610mb", 106 | "keccak256100kb", 107 | "keccak256300kb", 108 | "keccak2561mb", 109 | "keccak2563mb", 110 | "keccak25610mb", 111 | "tendermint", 112 | "ssz-withdrawals", 113 | "rsp20526626", 114 | "rsp20526627", 115 | "rsp20526628", 116 | "rsp20526629", 117 | "rsp20526630", 118 | "rsp20528708", 119 | "rsp20528709", 120 | "rsp20528710", 121 | "rsp20528711", 122 | "rsp20528712", 123 | "ecdsa-verify", 124 | "eddsa-verify", 125 | "helios", 126 | "groth16-proof-verify", 127 | "zk-email" 128 | ], 129 | help="List of programs to benchmark", 130 | choices=[ 131 | "loop10k", 132 | "loop100k", 133 | "loop1m", 134 | "loop3m", 135 | "loop10m", 136 | "loop30m", 137 | "loop100m", 138 | "loop300m", 139 | "fibonacci20k", 140 | "fibonacci200k", 141 | "fibonacci2m", 142 | "fibonacci4m", 143 | "fibonacci20m", 144 | "fibonacci40m", 145 | "fibonacci200m", 146 | "fibonacci400m", 147 | "fibonacci1b", 148 | "fibonacci2b", 149 | "fibonacci4b", 150 | "sha256100kb", 151 | "sha256300kb", 152 | "sha2561mb", 153 | "sha2563mb", 154 | "sha25610mb", 155 | "keccak256100kb", 156 | "keccak256300kb", 157 | "keccak2561mb", 158 | "keccak2563mb", 159 | "keccak25610mb", 160 | "tendermint", 161 | "ssz-withdrawals", 162 | "rsp20526626", 163 | "rsp20526627", 164 | "rsp20526628", 165 | "rsp20526629", 166 | "rsp20526630", 167 | "rsp20528708", 168 | "rsp20528709", 169 | "rsp20528710", 170 | "rsp20528711", 171 | "rsp20528712", 172 | "ecdsa-verify", 173 | "eddsa-verify", 174 | "helios", 175 | "groth16-proof-verify", 176 | "zk-email" 177 | ], 178 | ) 179 | parser.add_argument( 180 | "--provers", 181 | nargs="+", 182 | default=["risc0"], 183 | help="List of provers to use", 184 | choices=["sp1", "risc0"], 185 | ) 186 | parser.add_argument( 187 | "--hashfns", 188 | nargs="+", 189 | default=["poseidon"], 190 | help="List of hash functions to use", 191 | choices=["poseidon"], 192 | ) 193 | parser.add_argument( 194 | "--shard-sizes", 195 | type=int, 196 | nargs="+", 197 | default=[21], 198 | help="List of shard sizes to use", 199 | ) 200 | parser.add_argument("--block-1", default="17106222", help="Block number for reth1") 201 | parser.add_argument("--block-2", default="19409768", help="Block number for reth2") 202 | 203 | args = parser.parse_args() 204 | 205 | run_benchmark( 206 | args.filename, 207 | args.trials, 208 | args.programs, 209 | args.provers, 210 | args.hashfns, 211 | args.shard_sizes, 212 | args.block_1, 213 | args.block_2, 214 | ) 215 | 216 | 217 | if __name__ == "__main__": 218 | main() 219 | -------------------------------------------------------------------------------- /workflow_cpu.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | INSTANCES=( 4 | # "aws-m7i-xlarge" 5 | "aws-m7i-2xlarge" 6 | # "aws-m7i-4xlarge" 7 | # "aws-m7i-8xlarge" 8 | "aws-m7i-16xlarge" 9 | ) 10 | PROVERS=( 11 | "sp1" 12 | "risc0" 13 | ) 14 | SHARD_SIZES=( 15 | "21" 16 | ) 17 | PROGRAMS=( 18 | "loop10k" 19 | "loop100k" 20 | "loop1m" 21 | "loop3m" 22 | "loop10m" 23 | "fibonacci20k" 24 | "fibonacci200k" 25 | "fibonacci2m" 26 | "fibonacci4m" 27 | "fibonacci20m" 28 | "sha256300kb" 29 | "keccak256300kb" 30 | "ssz-withdrawals" 31 | "tendermint" 32 | # "ecdsa-verify" 33 | "eddsa-verify" 34 | "rsp20526626" 35 | ) 36 | 37 | # Get the current git branch. 38 | GIT_REF=$(git rev-parse --abbrev-ref HEAD) 39 | 40 | # Create a JSON object with the specified fields. 41 | WORKLOADS=$(jq -n \ 42 | --arg instances "$(printf '%s\n' "${INSTANCES[@]}" | jq -R . | jq -s 'map(select(length > 0))')" \ 43 | --arg provers "$(printf '%s\n' "${PROVERS[@]}" | jq -R . | jq -s 'map(select(length > 0))')" \ 44 | --arg shard_sizes "$(printf '%s\n' "${SHARD_SIZES[@]}" | jq -R . | jq -s 'map(select(length > 0))')" \ 45 | --arg programs "$(printf '%s\n' "${PROGRAMS[@]}" | jq -R . | jq -s 'map(select(length > 0))')" \ 46 | '{instances: $instances, provers: $provers, shard_sizes: $shard_sizes, programs: $programs}') 47 | 48 | # Run the workflow with the list of workloads. 49 | echo $WORKLOADS | gh workflow run suite.yml --ref $GIT_REF --json -------------------------------------------------------------------------------- /workflow_gpu.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | INSTANCES=( 3 | "aws-g6-xlarge" 4 | "aws-g6-2xlarge" 5 | ) 6 | PROVERS=( 7 | "sp1" 8 | "risc0" 9 | ) 10 | SHARD_SIZES=( 11 | "21" 12 | ) 13 | PROGRAMS=( 14 | "loop10k" 15 | "loop100k" 16 | "loop1m" 17 | "loop3m" 18 | "loop10m" 19 | "loop30m" 20 | "loop100m" 21 | "loop300m" 22 | "fibonacci20k" 23 | "fibonacci200k" 24 | "fibonacci2m" 25 | "fibonacci4m" 26 | "fibonacci20m" 27 | "fibonacci40m" 28 | "fibonacci200m" 29 | "fibonacci400m" 30 | "sha256100kb" 31 | "sha256300kb" 32 | "sha2561mb" 33 | "sha2563mb" 34 | "keccak256100kb" 35 | "keccak256300kb" 36 | "keccak2561mb" 37 | "keccak2563mb" 38 | "ssz-withdrawals" 39 | "tendermint" 40 | "rsp20526626" 41 | "rsp20526627" 42 | "rsp20526628" 43 | "rsp20526629" 44 | "rsp20526630" 45 | "rsp20528708" 46 | "rsp20528709" 47 | "rsp20528710" 48 | "rsp20528711" 49 | "rsp20528712" 50 | # "ecdsa-verify" 51 | "eddsa-verify" 52 | "helios" 53 | "groth16-proof-verify" 54 | "zk-email" 55 | ) 56 | # Get the current git branch. 57 | GIT_REF=$(git rev-parse --abbrev-ref HEAD) 58 | # Create a JSON object with the specified fields. 59 | WORKLOADS=$(jq -n \ 60 | --arg instances "$(printf '%s\n' "${INSTANCES[@]}" | jq -R . | jq -s 'map(select(length > 0))')" \ 61 | --arg provers "$(printf '%s\n' "${PROVERS[@]}" | jq -R . | jq -s 'map(select(length > 0))')" \ 62 | --arg shard_sizes "$(printf '%s\n' "${SHARD_SIZES[@]}" | jq -R . | jq -s 'map(select(length > 0))')" \ 63 | --arg programs "$(printf '%s\n' "${PROGRAMS[@]}" | jq -R . | jq -s 'map(select(length > 0))')" \ 64 | '{instances: $instances, provers: $provers, shard_sizes: $shard_sizes, programs: $programs}') 65 | # Run the workflow with the list of workloads. 66 | echo $WORKLOADS | gh workflow run suite.yml --ref $GIT_REF --json --------------------------------------------------------------------------------