diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..5b3ca8c2a --- /dev/null +++ b/.dockerignore @@ -0,0 +1,9 @@ +**/target +Dockerfile* +.dockerignore +.git +.gitignore +examples +tests +sp1up +book diff --git a/.github/workflows/docker-publish-gnark.yml b/.github/workflows/docker-publish-gnark.yml new file mode 100644 index 000000000..c36a28d30 --- /dev/null +++ b/.github/workflows/docker-publish-gnark.yml @@ -0,0 +1,102 @@ +# Source: https://raw.githubusercontent.com/foundry-rs/foundry/master/.github/workflows/docker-publish.yml +name: docker-gnark + +on: + push: + tags: + - "v*.*.*" + schedule: + - cron: "0 0 * * *" + # Trigger without any parameters a proactive rebuild + workflow_dispatch: + inputs: + tags: + description: "Docker tag to push" + required: true + workflow_call: + +env: + REGISTRY: ghcr.io + IMAGE_NAME: succinctlabs/sp1-gnark + +jobs: + container: + runs-on: ubuntu-latest + # https://docs.github.com/en/actions/reference/authentication-in-a-workflow + permissions: + id-token: write + packages: write + contents: read + timeout-minutes: 120 + steps: + - name: Checkout repository + id: checkout + uses: actions/checkout@v4 + + - name: Install Docker BuildX + uses: docker/setup-buildx-action@v2 + id: buildx + with: + install: true + + # Login against a Docker registry except on PR + # https://github.com/docker/login-action + - name: Log into registry ${{ env.REGISTRY }} + # Ensure this doesn't trigger on PR's + if: github.event_name != 'pull_request' + uses: docker/login-action@v2 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + # Extract metadata (tags, labels) for Docker + # https://github.com/docker/metadata-action + - name: Extract Docker metadata + id: meta + uses: docker/metadata-action@v4 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + + # Creates an additional 'latest' or 'nightly' tag + # If the job is triggered via cron schedule, tag nightly and nightly-{SHA} + # If the job is triggered via workflow dispatch and on a master branch, tag branch and latest + # Otherwise, just tag as the branch name + - name: Finalize Docker Metadata + id: docker_tagging + run: | + if [[ "${{ github.event_name }}" == 'workflow_dispatch' ]]; then + echo "manual trigger from workflow_dispatch, assigning tag ${{ github.event.inputs.tags }}" + echo "docker_tags=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.event.inputs.tags }}" >> $GITHUB_OUTPUT + elif [[ "${{ github.event_name }}" == 'schedule' ]]; then + echo "cron trigger, assigning nightly tag" + echo "docker_tags=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:nightly,${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:nightly-${GITHUB_SHA}" >> $GITHUB_OUTPUT + else + echo "Neither scheduled nor manual release from main branch. Just tagging as branch name" + echo "docker_tags=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${GITHUB_REF##*/}" >> $GITHUB_OUTPUT + fi + + # Log docker metadata to explicitly know what is being pushed + - name: Inspect Docker Metadata + run: | + echo "TAGS -> ${{ steps.docker_tagging.outputs.docker_tags }}" + echo "LABELS -> ${{ steps.meta.outputs.labels }}" + + # Build and push Docker image + # https://github.com/docker/build-push-action + # https://github.com/docker/build-push-action/blob/master/docs/advanced/cache.md + - name: Build and push Docker image + uses: docker/build-push-action@v3 + with: + context: . + file: ./Dockerfile.gnark-ffi + platforms: linux/amd64,linux/arm64 + push: true + tags: ${{ steps.docker_tagging.outputs.docker_tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max + build-args: | + BUILDTIME=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.created'] }} + VERSION=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.version'] }} + REVISION=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.revision'] }} diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index a2e352a59..fc14a2ca7 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -29,7 +29,6 @@ jobs: - name: Run cargo test with no default features run: | cargo nextest run -p sphinx-core --cargo-profile dev-ci --profile ci --no-default-features --features "debug" -E 'test(cpu::trace::tests)' - working-directory: ${{ github.workspace }}/examples test-recursion-circuit: name: Test recursion circuit diff --git a/.gitignore b/.gitignore index e5b76a0c3..42ef47a62 100644 --- a/.gitignore +++ b/.gitignore @@ -9,8 +9,8 @@ pgo-data.profdata .DS_Store # Proofs -**/proof-with-pis.json -**/proof-with-io.json +**/proof-with-pis.bin +**/proof-with-io.bin # Benchmark benchmark.csv diff --git a/.vscode/settings.json b/.vscode/settings.json index 952af6da3..4ee645ef8 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -40,7 +40,6 @@ // "examples/tendermint/script/Cargo.toml", // // Tests. // "examples/ed25519/Cargo.toml", - // "tests/blake3-compress/Cargo.toml", // "tests/cycle-tracker/Cargo.toml", // "tests/ecrecover/Cargo.toml", // "tests/ed-add/Cargo.toml", diff --git a/Cargo.lock b/Cargo.lock index 7a6f3e70c..783cdee1a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -630,16 +630,16 @@ dependencies = [ [[package]] name = "blake3" -version = "1.5.1" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30cca6d3674597c30ddf2c587bf8d9d65c9a84d2326d941cc79c9842dfe0ef52" +checksum = "e9ec96fe9a81b5e365f9db71fe00edc4fe4ca2cc7dcb7861f0603012a7caa210" dependencies = [ "arrayref", "arrayvec", "cc", "cfg-if", "constant_time_eq", - "rayon", + "rayon-core", ] [[package]] @@ -699,6 +699,12 @@ version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" +[[package]] +name = "bytemuck" +version = "1.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e" + [[package]] name = "byteorder" version = "1.5.0" @@ -1713,21 +1719,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "form_urlencoded" version = "1.2.1" @@ -2191,19 +2182,21 @@ dependencies = [ ] [[package]] -name = "hyper-tls" -version = "0.6.0" +name = "hyper-rustls" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" dependencies = [ - "bytes", - "http-body-util", + "futures-util", + "http 1.1.0", "hyper 1.3.1", "hyper-util", - "native-tls", + "rustls", + "rustls-pki-types", "tokio", - "tokio-native-tls", + "tokio-rustls", "tower-service", + "webpki-roots", ] [[package]] @@ -2435,7 +2428,7 @@ checksum = "6971da4d9c3aa03c3d8f3ff0f4155b534aad021292003895a469716b2a230378" dependencies = [ "base64 0.21.7", "pem", - "ring", + "ring 0.16.20", "serde", "serde_json", "simple_asn1", @@ -2630,23 +2623,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "native-tls" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" -dependencies = [ - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - [[package]] name = "nohash-hasher" version = "0.2.0" @@ -2879,50 +2855,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "openssl" -version = "0.10.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" -dependencies = [ - "bitflags 2.5.0", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.68", -] - -[[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "openssl-sys" -version = "0.9.102" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "overload" version = "0.1.1" @@ -3552,6 +3484,53 @@ version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" +[[package]] +name = "quinn" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4ceeeeabace7857413798eb1ffa1e9c905a9946a57d81fb69b4b71c4d8eb3ad" +dependencies = [ + "bytes", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "quinn-proto" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddf517c03a109db8100448a4be38d498df8a210a99fe0e1b9eaf39e78c640efe" +dependencies = [ + "bytes", + "rand", + "ring 0.17.8", + "rustc-hash", + "rustls", + "slab", + "thiserror", + "tinyvec", + "tracing", +] + +[[package]] +name = "quinn-udp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9096629c45860fc7fb143e125eb826b5e721e10be3263160c7d60ca832cf8c46" +dependencies = [ + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.52.0", +] + [[package]] name = "quote" version = "1.0.36" @@ -3738,23 +3717,25 @@ dependencies = [ "http-body 1.0.0", "http-body-util", "hyper 1.3.1", - "hyper-tls", + "hyper-rustls", "hyper-util", "ipnet", "js-sys", "log", "mime", - "native-tls", "once_cell", "percent-encoding", "pin-project-lite", + "quinn", + "rustls", "rustls-pemfile", + "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper 1.0.1", "tokio", - "tokio-native-tls", + "tokio-rustls", "tokio-util", "tower-service", "url", @@ -3762,6 +3743,7 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", + "webpki-roots", "winreg 0.52.0", ] @@ -3800,11 +3782,26 @@ dependencies = [ "libc", "once_cell", "spin 0.5.2", - "untrusted", + "untrusted 0.7.1", "web-sys", "winapi", ] +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin 0.9.8", + "untrusted 0.9.0", + "windows-sys 0.52.0", +] + [[package]] name = "ripemd" version = "0.1.3" @@ -3925,6 +3922,20 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rustls" +version = "0.23.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" +dependencies = [ + "once_cell", + "ring 0.17.8", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + [[package]] name = "rustls-pemfile" version = "2.1.2" @@ -3941,6 +3952,17 @@ version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" +[[package]] +name = "rustls-webpki" +version = "0.102.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e" +dependencies = [ + "ring 0.17.8", + "rustls-pki-types", + "untrusted 0.9.0", +] + [[package]] name = "rustversion" version = "1.0.17" @@ -4016,15 +4038,6 @@ dependencies = [ "sdd", ] -[[package]] -name = "schannel" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" -dependencies = [ - "windows-sys 0.52.0", -] - [[package]] name = "scopeguard" version = "1.2.0" @@ -4063,29 +4076,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "security-framework" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" -dependencies = [ - "bitflags 2.5.0", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "semver" version = "0.11.0" @@ -4385,6 +4375,7 @@ dependencies = [ "bincode", "blake3", "bls12_381 0.8.0", + "bytemuck", "cfg-if", "criterion", "curve25519-dalek", @@ -4615,6 +4606,7 @@ dependencies = [ "p3-merkle-tree", "p3-poseidon2", "p3-symmetric", + "p3-util", "rand", "serde", "serde_with", @@ -4639,8 +4631,11 @@ dependencies = [ name = "sphinx-recursion-gnark-ffi" version = "1.0.0" dependencies = [ + "anyhow", + "bincode", "bindgen", "cfg-if", + "hex", "log", "num-bigint 0.4.5", "p3-baby-bear", @@ -4649,6 +4644,7 @@ dependencies = [ "rand", "serde", "serde_json", + "sha2", "sphinx-core", "sphinx-recursion-compiler", "tempfile", @@ -4711,6 +4707,7 @@ dependencies = [ "strum", "strum_macros", "tempfile", + "thiserror", "tokio", "tracing", "twirp", @@ -4725,6 +4722,8 @@ dependencies = [ "cfg-if", "getrandom", "k256", + "lazy_static", + "libm", "once_cell", "p3-baby-bear", "p3-field", @@ -5024,12 +5023,13 @@ dependencies = [ ] [[package]] -name = "tokio-native-tls" -version = "0.3.1" +name = "tokio-rustls" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "native-tls", + "rustls", + "rustls-pki-types", "tokio", ] @@ -5327,6 +5327,12 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" version = "2.5.2" @@ -5518,6 +5524,15 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki-roots" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "which" version = "4.4.2" diff --git a/Cargo.toml b/Cargo.toml index 97d8b5d95..75efc2756 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -60,6 +60,7 @@ axum = "=0.7.5" backtrace = "0.3.73" bincode = "1.3.3" blake3 = "1.5" +bytemuck = "1.16.1" cargo_metadata = "0.18.1" cfg-if = "1.0.0" chrono = { version = "0.4.38", default-features = false } diff --git a/Dockerfile.gnark-ffi b/Dockerfile.gnark-ffi new file mode 100644 index 000000000..3e0624d79 --- /dev/null +++ b/Dockerfile.gnark-ffi @@ -0,0 +1,33 @@ +FROM golang:1.22 AS go-builder + +FROM rustlang/rust:nightly-bullseye-slim AS rust-builder + +# Dependencies +RUN apt update && apt install -y clang + +# Install Go 1.22 +COPY --from=go-builder /usr/local/go /usr/local/go +ENV PATH="/usr/local/go/bin:$PATH" + +WORKDIR /sp1 + +# Install Rust toolchain +COPY ./rust-toolchain /sp1/rust-toolchain +RUN rustup show + +# Copy repo +COPY . /sp1 + +# Build the gnark-ffi CLI +WORKDIR /sp1/recursion/gnark-cli + +RUN \ + --mount=type=cache,target=target \ + cargo build --release && cp target/release/sp1-recursion-gnark-cli /gnark-cli + +FROM rustlang/rust:nightly-bullseye-slim +COPY --from=rust-builder /gnark-cli /gnark-cli + +LABEL org.opencontainers.image.source=https://github.com/succinctlabs/sp1 + +ENTRYPOINT ["/gnark-cli"] \ No newline at end of file diff --git a/cli/Cargo.toml b/cli/Cargo.toml index bd0c20fd4..7b61d814c 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -15,7 +15,7 @@ clap = { workspace = true, features = ["derive", "env"] } sphinx-prover = { path = "../prover" } sphinx-sdk = { path = "../sdk" } sphinx-core = { path = "../core" } -reqwest = { workspace = true, features = ["stream", "json", "default-tls"] } +reqwest = { workspace = true, features = ["stream", "json", "rustls-tls"] } futures-util = { workspace = true } indicatif = { workspace = true } tokio = { workspace = true, features = ["full"] } diff --git a/cli/docker/Dockerfile b/cli/docker/Dockerfile index c07493c83..b8b35b346 100644 --- a/cli/docker/Dockerfile +++ b/cli/docker/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:22.04@sha256:bcc511d82482900604524a8e8d64bf4c53b2461868dac55f4d04d660e61983cb +FROM ubuntu:24.04@sha256:e3f92abc0967a6c19d0dfa2d55838833e947b9d74edbcb0113e48535ad4be12a RUN apt-get update RUN apt-get install -y --no-install-recommends ca-certificates clang curl libssl-dev pkg-config git dialog diff --git a/cli/src/assets/.gitignore b/cli/src/assets/.gitignore deleted file mode 100644 index 0be6e7269..000000000 --- a/cli/src/assets/.gitignore +++ /dev/null @@ -1,16 +0,0 @@ -# Cargo build -**/target - -# Cargo config -.cargo - -# Profile-guided optimization -/tmp -pgo-data.profdata - -# MacOS nuisances -.DS_Store - -# Proofs -**/proof-with-pis.json -**/proof-with-io.json diff --git a/cli/src/assets/.vscode/settings.json b/cli/src/assets/.vscode/settings.json deleted file mode 100644 index d43ccf804..000000000 --- a/cli/src/assets/.vscode/settings.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "editor.inlineSuggest.enabled": true, - "[rust]": { - "editor.defaultFormatter": "rust-lang.rust-analyzer", - }, - "editor.rulers": [ - 100 - ], - "rust-analyzer.check.overrideCommand": [ - "cargo", - "clippy", - "--workspace", - "--message-format=json", - "--all-features", - "--all-targets", - "--", - "-A", - "incomplete-features" - ], - "rust-analyzer.linkedProjects": [ - "program/Cargo.toml", - "script/Cargo.toml", - ], - "rust-analyzer.showUnlinkedFileNotification": false -} \ No newline at end of file diff --git a/cli/src/assets/program/Cargo.toml b/cli/src/assets/program/Cargo.toml deleted file mode 100644 index 0517ea061..000000000 --- a/cli/src/assets/program/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[workspace] -[package] -version = "0.1.0" -name = "unnamed-program" -edition = "2021" - -[dependencies] -sphinx-zkvm = { git = "ssh://git@github.com/lurk-lab/sphinx.git" } \ No newline at end of file diff --git a/cli/src/assets/program/main.rs b/cli/src/assets/program/main.rs deleted file mode 100644 index 398434267..000000000 --- a/cli/src/assets/program/main.rs +++ /dev/null @@ -1,22 +0,0 @@ -//! A simple program to be proven inside the zkVM. - -#![no_main] -sphinx_zkvm::entrypoint!(main); - -pub fn main() { - // NOTE: values of n larger than 186 will overflow the u128 type, - // resulting in output that doesn't match fibonacci sequence. - // However, the resulting proof will still be valid! - let n = sphinx_zkvm::io::read::(); - let mut a: u128 = 0; - let mut b: u128 = 1; - let mut sum: u128; - for _ in 1..n { - sum = a + b; - a = b; - b = sum; - } - - sphinx_zkvm::io::commit(&a); - sphinx_zkvm::io::commit(&b); -} diff --git a/cli/src/assets/script/Cargo.toml b/cli/src/assets/script/Cargo.toml deleted file mode 100644 index 207a506e6..000000000 --- a/cli/src/assets/script/Cargo.toml +++ /dev/null @@ -1,11 +0,0 @@ -[workspace] -[package] -version = "0.1.0" -name = "unnamed-script" -edition = "2021" - -[dependencies] -sphinx-sdk = { git = "ssh://git@github.com/lurk-lab/sphinx.git" } - -[build-dependencies] -sphinx-helper = { git = "ssh://git@github.com/lurk-lab/sphinx.git" } \ No newline at end of file diff --git a/cli/src/assets/script/build.rs b/cli/src/assets/script/build.rs deleted file mode 100644 index f1c66e12a..000000000 --- a/cli/src/assets/script/build.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - sphinx_helper::build_program(&format!("{}/../program", env!("CARGO_MANIFEST_DIR"))); -} diff --git a/cli/src/assets/script/main.rs b/cli/src/assets/script/main.rs deleted file mode 100644 index 8016ecac0..000000000 --- a/cli/src/assets/script/main.rs +++ /dev/null @@ -1,37 +0,0 @@ -//! A simple script to generate and verify the proof of a given program. - -use sphinx_sdk::{utils, ProverClient, SphinxStdin}; - -/// The ELF we want to execute inside the zkVM. -const ELF: &[u8] = include_bytes!("../../program/elf/riscv32im-succinct-zkvm-elf"); - -fn main() { - // Setup logging. - utils::setup_logger(); - - // Generate proof. - let mut stdin = SphinxStdin::new(); - let n = 186u32; - stdin.write(&n); - let client = ProverClient::new(); - let (pk, vk) = client.setup(ELF); - let mut proof = client.prove_compressed(&pk, stdin).expect("proving failed"); - - // Read output. - let a = proof.public_values.read::(); - let b = proof.public_values.read::(); - println!("a: {}", a); - println!("b: {}", b); - - // Verify proof. - client - .verify_compressed(&proof, &vk) - .expect("verification failed"); - - // Save proof. - proof - .save("proof-with-io.json") - .expect("saving proof failed"); - - println!("successfully generated and verified proof for the program!") -} diff --git a/cli/src/commands/build_toolchain.rs b/cli/src/commands/build_toolchain.rs index f95a4c0ad..22a786155 100644 --- a/cli/src/commands/build_toolchain.rs +++ b/cli/src/commands/build_toolchain.rs @@ -120,7 +120,7 @@ impl BuildToolchainCmd { for tool in tools_bin_dir.read_dir()? { let tool = tool?; let tool_name = tool.file_name(); - std::fs::copy(&tool.path(), target_bin_dir.join(tool_name))?; + std::fs::copy(tool.path(), target_bin_dir.join(tool_name))?; } // Link the toolchain to rustup. diff --git a/cli/src/commands/install_toolchain.rs b/cli/src/commands/install_toolchain.rs index a72793664..6a9db3f3f 100644 --- a/cli/src/commands/install_toolchain.rs +++ b/cli/src/commands/install_toolchain.rs @@ -11,7 +11,9 @@ use std::process::Command; #[cfg(target_family = "unix")] use std::os::unix::fs::PermissionsExt; -use crate::{get_target, get_toolchain_download_url, url_exists, RUSTUP_TOOLCHAIN_NAME}; +use crate::{ + get_target, get_toolchain_download_url, is_supported_target, url_exists, RUSTUP_TOOLCHAIN_NAME, +}; #[derive(Parser)] #[command( @@ -58,6 +60,11 @@ impl InstallToolchainCmd { Ok(_) => println!("Successfully created ~/.sp1 directory."), Err(err) => println!("Failed to create ~/.sp1 directory: {}", err), }; + + assert!( + is_supported_target(), + "Unsupported architecture. Please build the toolchain from source." + ); let target = get_target(); let toolchain_asset_name = format!("rust-toolchain-{}.tar.gz", target); let toolchain_archive_path = root_dir.join(toolchain_asset_name.clone()); diff --git a/cli/src/commands/new.rs b/cli/src/commands/new.rs index 7ae8a00f5..e5408a422 100644 --- a/cli/src/commands/new.rs +++ b/cli/src/commands/new.rs @@ -1,61 +1,49 @@ -use std::{fs, path::Path}; - use anyhow::Result; use clap::Parser; +use std::{fs, path::Path, process::Command}; use yansi::Paint; -const PROGRAM_CARGO_TOML: &str = include_str!("../assets/program/Cargo.toml"); -const PROGRAM_MAIN_RS: &str = include_str!("../assets/program/main.rs"); -const SCRIPT_CARGO_TOML: &str = include_str!("../assets/script/Cargo.toml"); -const SCRIPT_MAIN_RS: &str = include_str!("../assets/script/main.rs"); -const SCRIPT_BUILD_RS: &str = include_str!("../assets/script/build.rs"); -const GIT_IGNORE: &str = include_str!("../assets/.gitignore"); -const VS_CODE_SETTINGS_JSON: &str = include_str!("../assets/.vscode/settings.json"); - #[derive(Parser)] #[command(name = "new", about = "Setup a new project that runs inside the SP1.")] pub struct NewCmd { name: String, } +const TEMPLATE_REPOSITORY_URL: &str = "https://github.com/succinctlabs/sp1-project-template"; + impl NewCmd { pub fn run(&self) -> Result<()> { let root = Path::new(&self.name); - let program_root = root.join("program"); - let script_root = root.join("script"); - - // Create the root directory. - fs::create_dir(&self.name)?; - - // Create the program directory. - fs::create_dir(&program_root)?; - fs::create_dir(program_root.join("src"))?; - fs::create_dir(program_root.join("elf"))?; - fs::write( - program_root.join("Cargo.toml"), - PROGRAM_CARGO_TOML.replace("unnamed", &self.name), - )?; - fs::write(program_root.join("src").join("main.rs"), PROGRAM_MAIN_RS)?; - - // Create the runner directory. - fs::create_dir(&script_root)?; - fs::create_dir(script_root.join("src"))?; - fs::write( - script_root.join("Cargo.toml"), - SCRIPT_CARGO_TOML.replace("unnamed", &self.name), - )?; - fs::write(script_root.join("src").join("main.rs"), SCRIPT_MAIN_RS)?; - fs::write(script_root.join("build.rs"), SCRIPT_BUILD_RS)?; - - // Add .gitignore file to root. - fs::write(root.join(".gitignore"), GIT_IGNORE)?; - // Add .vscode/settings.json to root. - fs::create_dir(root.join(".vscode"))?; - fs::write( - root.join(".vscode").join("settings.json"), - VS_CODE_SETTINGS_JSON, - )?; + // Create the root directory if it doesn't exist. + if !root.exists() { + fs::create_dir(&self.name)?; + } + + // Clone the repository. + let output = Command::new("git") + .arg("clone") + .arg(TEMPLATE_REPOSITORY_URL) + .arg(root.as_os_str()) + .arg("--recurse-submodules") + .arg("--depth=1") + .output() + .expect("failed to execute command"); + if !output.status.success() { + let stderr = String::from_utf8_lossy(&output.stderr); + return Err(anyhow::anyhow!("failed to clone repository: {}", stderr)); + } + + // Remove the .git directory. + fs::remove_dir_all(root.join(".git"))?; + + // Check if the user has `foundry` installed. + if Command::new("foundry").arg("--version").output().is_err() { + println!( + " \x1b[1m{}\x1b[0m Make sure to install Foundry to use contracts: https://book.getfoundry.sh/getting-started/installation.", + Paint::yellow("Warning:"), + ); + } println!( " \x1b[1m{}\x1b[0m {} ({})", diff --git a/cli/src/lib.rs b/cli/src/lib.rs index c26c48617..00fe15062 100644 --- a/cli/src/lib.rs +++ b/cli/src/lib.rs @@ -38,6 +38,23 @@ pub async fn url_exists(client: &Client, url: &str) -> bool { res.is_ok() } +#[allow(unreachable_code)] +pub fn is_supported_target() -> bool { + #[cfg(all(target_arch = "x86_64", target_os = "linux"))] + return true; + + #[cfg(all(target_arch = "aarch64", target_os = "linux"))] + return true; + + #[cfg(all(target_arch = "x86_64", target_os = "macos"))] + return true; + + #[cfg(all(target_arch = "aarch64", target_os = "macos"))] + return true; + + false +} + pub fn get_target() -> String { target_lexicon::HOST.to_string() } diff --git a/core/Cargo.toml b/core/Cargo.toml index 8a941e56c..6a8ad6f0c 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -39,6 +39,7 @@ anyhow = { workspace = true } arrayref = { workspace = true } blake3 = { workspace = true } bls12_381 = { workspace = true } +bytemuck = { workspace = true } cfg-if = { workspace = true } curve25519-dalek = { workspace = true } elliptic-curve = { workspace = true } @@ -74,6 +75,7 @@ debug = [] default = ["avx512"] keccak = [] neon = ["p3-blake3/neon"] +programs = [] serial = [] avx512 = ["p3-baby-bear/nightly-features"] diff --git a/core/src/bytes/mod.rs b/core/src/bytes/mod.rs index 388e6910b..c6ab258fe 100644 --- a/core/src/bytes/mod.rs +++ b/core/src/bytes/mod.rs @@ -5,19 +5,19 @@ pub mod opcode; pub mod trace; pub mod utils; +pub use event::ByteLookupEvent; +pub use opcode::*; + use core::borrow::BorrowMut; +use std::collections::BTreeMap; use std::marker::PhantomData; -pub use event::ByteLookupEvent; use itertools::Itertools; -pub use opcode::*; use p3_field::Field; use p3_matrix::dense::RowMajorMatrix; -use self::{ - columns::{BytePreprocessedCols, NUM_BYTE_PREPROCESSED_COLS}, - utils::shr_carry, -}; +use self::columns::{BytePreprocessedCols, NUM_BYTE_PREPROCESSED_COLS}; +use self::utils::shr_carry; use crate::bytes::trace::NUM_ROWS; /// The number of different byte operations. @@ -34,10 +34,19 @@ pub const NUM_BYTE_LOOKUP_CHANNELS: u32 = 16; pub struct ByteChip(PhantomData); impl ByteChip { - /// Creates the preprocessed byte trace. + /// Creates the preprocessed byte trace and event map. /// - /// This function returns a `trace` which is a matrix containing all possible byte operations. - pub fn trace() -> RowMajorMatrix { + /// This function returns a pair `(trace, map)`, where: + /// - `trace` is a matrix containing all possible byte operations. + /// - `map` is a map from a byte lookup to the corresponding row it appears in the table and + /// the index of the result in the array of multiplicities. + pub fn trace_and_map( + shard: u32, + ) -> (RowMajorMatrix, BTreeMap) { + // A map from a byte lookup to its corresponding row in the table and index in the array of + // multiplicities. + let mut event_map = BTreeMap::new(); + // The trace containing all values, with all multiplicities set to zero. let mut initial_trace = RowMajorMatrix::new( vec![F::zero(); NUM_ROWS * NUM_BYTE_PREPROCESSED_COLS], @@ -55,11 +64,10 @@ impl ByteChip { col.b = F::from_canonical_u8(b); col.c = F::from_canonical_u8(c); - let shard = 0; // Iterate over all operations for results and updating the table map. for channel in 0..NUM_BYTE_LOOKUP_CHANNELS { - for opcode in opcodes.iter() { - match opcode { + for (i, opcode) in opcodes.iter().enumerate() { + let event = match opcode { ByteOpcode::AND => { let and = b & c; col.and = F::from_canonical_u8(and); @@ -158,7 +166,7 @@ impl ByteChip { u32::from(msb), 0, u32::from(b), - 0_u32, + 0u32, ) } ByteOpcode::U16Range => { @@ -167,25 +175,11 @@ impl ByteChip { ByteLookupEvent::new(shard, channel, *opcode, v, 0, 0, 0) } }; + event_map.insert(event, (row_index, i)); } } } - initial_trace - } -} - -#[cfg(test)] -mod tests { - use p3_baby_bear::BabyBear; - use std::time::Instant; - - use super::*; - - #[test] - fn test_trace_and_map() { - let start = Instant::now(); - ByteChip::::trace(); - println!("trace and map: {:?}", start.elapsed()); + (initial_trace, event_map) } } diff --git a/core/src/bytes/trace.rs b/core/src/bytes/trace.rs index 0d9cbfbfa..85430dfc5 100644 --- a/core/src/bytes/trace.rs +++ b/core/src/bytes/trace.rs @@ -35,7 +35,10 @@ impl MachineAir for ByteChip { } fn generate_preprocessed_trace(&self, _program: &Self::Program) -> Option> { - let trace = Self::trace(); + // OPT: We should be able to make this a constant. Also, trace / map should be separate. + // Since we only need the trace and not the map, we can just pass 0 as the shard. + let (trace, _) = Self::trace_and_map(0); + Some(trace) } diff --git a/core/src/cpu/columns/memory.rs b/core/src/cpu/columns/memory.rs index 30e458f36..83cd1525e 100644 --- a/core/src/cpu/columns/memory.rs +++ b/core/src/cpu/columns/memory.rs @@ -1,4 +1,4 @@ -use std::{array, mem::size_of}; +use std::mem::size_of; use sphinx_derive::AlignedBorrow; @@ -7,7 +7,7 @@ use crate::{air::Word, memory::MemoryReadWriteCols, operations::BabyBearWordRang pub const NUM_MEMORY_COLUMNS: usize = size_of::>(); /// The column layout for memory. -#[derive(AlignedBorrow, Debug, Clone, Copy)] +#[derive(AlignedBorrow, Debug, Clone, Copy, Default)] #[repr(C)] pub struct MemoryColumns { // An addr that we are reading from or writing to as a word. We are guaranteed that this does @@ -37,22 +37,3 @@ pub struct MemoryColumns { pub addr_word_nonce: T, pub unsigned_mem_val_nonce: T, } - -impl Default for MemoryColumns { - fn default() -> Self { - MemoryColumns { - addr_word: Word::default(), - addr_aligned: T::default(), - addr_offset: T::default(), - memory_access: MemoryReadWriteCols::default(), - offset_is_one: T::default(), - offset_is_two: T::default(), - offset_is_three: T::default(), - most_sig_byte_decomp: array::from_fn(|_| T::default()), - addr_word_range_checker: BabyBearWordRangeChecker::::default(), - aa_least_sig_byte_decomp: array::from_fn(|_| T::default()), - addr_word_nonce: T::default(), - unsigned_mem_val_nonce: T::default(), - } - } -} diff --git a/core/src/cpu/trace.rs b/core/src/cpu/trace.rs index 53b2584db..4135b2983 100644 --- a/core/src/cpu/trace.rs +++ b/core/src/cpu/trace.rs @@ -4,15 +4,17 @@ use std::borrow::BorrowMut; use p3_field::{PrimeField, PrimeField32}; use p3_matrix::dense::RowMajorMatrix; -use p3_maybe_rayon::prelude::{ - IntoParallelRefMutIterator, ParallelBridge, ParallelIterator, ParallelSlice, ParallelSliceMut, -}; +use p3_maybe_rayon::prelude::IntoParallelRefIterator; +use p3_maybe_rayon::prelude::ParallelIterator; +use p3_maybe_rayon::prelude::ParallelSlice; use tracing::instrument; use super::columns::{CPU_COL_MAP, NUM_CPU_COLS}; use super::{CpuChip, CpuEvent}; +use crate::air::EventLens; +use crate::air::MachineAir; +use crate::air::WithEvents; use crate::air::Word; -use crate::air::{EventLens, MachineAir, WithEvents}; use crate::alu::create_alu_lookups; use crate::alu::AluEvent; use crate::bytes::event::ByteRecord; @@ -40,28 +42,47 @@ impl MachineAir for CpuChip { fn generate_trace>( &self, input: &EL, - _: &mut ExecutionRecord, + output: &mut ExecutionRecord, ) -> RowMajorMatrix { let (events, nonce_lookup) = input.events(); - let mut values = vec![F::zero(); events.len() * NUM_CPU_COLS]; - let chunk_size = std::cmp::max(events.len() / num_cpus::get(), 1); - values - .chunks_mut(chunk_size * NUM_CPU_COLS) - .enumerate() - .par_bridge() - .for_each(|(i, rows)| { - rows.chunks_mut(NUM_CPU_COLS) - .enumerate() - .for_each(|(j, row)| { - let idx = i * chunk_size + j; - let cols: &mut CpuCols = row.borrow_mut(); - self.event_to_row(&events[idx], nonce_lookup, cols); - }); - }); + let mut new_alu_events = HashMap::new(); + let mut new_blu_events = Vec::new(); + + // Generate the trace rows for each event. + let mut rows_with_events = events + .par_iter() + .map(|op: &CpuEvent| self.event_to_row::(*op, nonce_lookup)) + .collect::>(); + + // No need to sort by the shard, since the cpu events are already partitioned by that. + rows_with_events.sort_unstable_by_key(|(event, _, _)| event[CPU_COL_MAP.clk]); + + let mut rows = Vec::::new(); + for row_with_events in rows_with_events { + let (row, alu_events, blu_events) = row_with_events; + rows.extend(row); + for (key, value) in alu_events { + new_alu_events + .entry(key) + .and_modify(|op_new_events: &mut Vec| { + op_new_events.extend(value.clone()) + }) + .or_insert(value); + } + new_blu_events.extend(blu_events); + } + + // Add the dependency events to the shard. + for (_, value) in new_alu_events.iter_mut() { + value.sort_unstable_by_key(|event| event.clk); + } + new_blu_events.sort_unstable_by_key(|event| event.a1); + output.add_alu_events(&mut new_alu_events); + output.add_byte_lookup_events(new_blu_events); // Convert the trace to a row major matrix. - let mut trace = RowMajorMatrix::new(values, NUM_CPU_COLS); + let mut trace = RowMajorMatrix::new(rows, NUM_CPU_COLS); // Pad the trace to a power of two. Self::pad_to_power_of_two::(&mut trace.values); @@ -72,37 +93,33 @@ impl MachineAir for CpuChip { #[instrument(name = "generate cpu dependencies", level = "debug", skip_all)] fn generate_dependencies>(&self, input: &EL, output: &mut ExecutionRecord) { // Generate the trace rows for each event. - let chunk_size = std::cmp::max(input.events().0.len() / num_cpus::get(), 1); - let (alu_events, blu_events): (Vec<_>, Vec<_>) = input - .events() - .0 + let (events, _) = input.events(); + + let chunk_size = std::cmp::max(events.len() / num_cpus::get(), 1); + let events = events .par_chunks(chunk_size) .map(|ops: &[CpuEvent]| { let mut alu = HashMap::new(); - let mut blu: Vec<_> = Vec::with_capacity(ops.len() * 8); + let mut blu: Vec<_> = Vec::default(); for op in ops.iter() { - let mut row = [F::zero(); NUM_CPU_COLS]; - let cols: &mut CpuCols = row.as_mut_slice().borrow_mut(); - let (alu_events, blu_events) = - self.event_to_row::(op, &HashMap::new(), cols); - for (key, value) in alu_events { + let (_, alu_events, blu_events) = self.event_to_row::(*op, &HashMap::new()); + alu_events.into_iter().for_each(|(key, value)| { alu.entry(key).or_insert(Vec::default()).extend(value); - } + }); blu.extend(blu_events); } (alu, blu) }) - .unzip(); - - for mut alu_events_chunk in alu_events { - output.add_alu_events(&mut alu_events_chunk); - } - - let mut blu_events = blu_events.into_iter().flatten().collect::>(); - blu_events.par_sort_unstable_by_key(|event| (event.shard, event.opcode)); + .collect::>(); - for blu_event in blu_events { - output.add_byte_lookup_event(blu_event); + for (mut alu_events, mut blu_events) in events { + for (_, value) in alu_events.iter_mut() { + value.sort_unstable_by_key(|event| event.clk); + } + // Add the dependency events to the shard. + output.add_alu_events(&mut alu_events); + blu_events.sort_unstable_by_key(|event| event.a1); + output.add_byte_lookup_events(blu_events); } } @@ -115,13 +132,19 @@ impl CpuChip { /// Create a row from an event. fn event_to_row( &self, - event: &CpuEvent, + event: CpuEvent, nonce_lookup: &HashMap, - cols: &mut CpuCols, - ) -> (HashMap>, Vec) { + ) -> ( + [F; NUM_CPU_COLS], + HashMap>, + Vec, + ) { let mut new_alu_events = HashMap::new(); let mut new_blu_events = Vec::new(); + let mut row = [F::zero(); NUM_CPU_COLS]; + let cols: &mut CpuCols = row.as_mut_slice().borrow_mut(); + // Populate shard and clk columns. self.populate_shard_clk(cols, event, &mut new_blu_events); @@ -215,27 +238,19 @@ impl CpuChip { // Assert that the instruction is not a no-op. cols.is_real = F::one(); - (new_alu_events, new_blu_events) + (row, new_alu_events, new_blu_events) } /// Populates the shard, channel, and clk related rows. fn populate_shard_clk( &self, cols: &mut CpuCols, - event: &CpuEvent, + event: CpuEvent, new_blu_events: &mut Vec, ) { cols.shard = F::from_canonical_u32(event.shard); cols.channel = F::from_canonical_u32(event.channel); - cols.clk = F::from_canonical_u32(event.clk); - - let clk_16bit_limb = event.clk & 0xffff; - let clk_8bit_limb = (event.clk >> 16) & 0xff; - cols.clk_16bit_limb = F::from_canonical_u32(clk_16bit_limb); - cols.clk_8bit_limb = F::from_canonical_u32(clk_8bit_limb); - cols.channel_selectors.populate(event.channel); - new_blu_events.push(ByteLookupEvent::new( event.shard, event.channel, @@ -245,6 +260,12 @@ impl CpuChip { 0, 0, )); + + cols.clk = F::from_canonical_u32(event.clk); + let clk_16bit_limb = event.clk & 0xffff; + cols.clk_16bit_limb = F::from_canonical_u32(clk_16bit_limb); + let clk_8bit_limb = (event.clk >> 16) & 0xff; + cols.clk_8bit_limb = F::from_canonical_u32(clk_8bit_limb); new_blu_events.push(ByteLookupEvent::new( event.shard, event.channel, @@ -269,7 +290,7 @@ impl CpuChip { fn populate_memory( &self, cols: &mut CpuCols, - event: &CpuEvent, + event: CpuEvent, new_alu_events: &mut HashMap>, new_blu_events: &mut Vec, nonce_lookup: &HashMap, @@ -378,8 +399,8 @@ impl CpuChip { cols.mem_value_is_neg = F::one(); let sub_event = AluEvent { lookup_id: event.memory_sub_lookup_id, - shard: event.shard, channel: event.channel, + shard: event.shard, clk: event.clk, opcode: Opcode::SUB, a: event.a, @@ -421,7 +442,7 @@ impl CpuChip { fn populate_branch( &self, cols: &mut CpuCols, - event: &CpuEvent, + event: CpuEvent, alu_events: &mut HashMap>, nonce_lookup: &HashMap, ) { @@ -550,7 +571,7 @@ impl CpuChip { fn populate_jump( &self, cols: &mut CpuCols, - event: &CpuEvent, + event: CpuEvent, alu_events: &mut HashMap>, nonce_lookup: &HashMap, ) { @@ -627,7 +648,7 @@ impl CpuChip { fn populate_auipc( &self, cols: &mut CpuCols, - event: &CpuEvent, + event: CpuEvent, alu_events: &mut HashMap>, nonce_lookup: &HashMap, ) { @@ -666,7 +687,7 @@ impl CpuChip { fn populate_ecall( &self, cols: &mut CpuCols, - event: &CpuEvent, + event: CpuEvent, nonce_lookup: &HashMap, ) -> bool { let mut is_halt = false; @@ -738,18 +759,22 @@ impl CpuChip { fn pad_to_power_of_two(values: &mut Vec) { let n_real_rows = values.len() / NUM_CPU_COLS; - - values.resize(n_real_rows.next_power_of_two() * NUM_CPU_COLS, F::zero()); + let padded_nb_rows = if n_real_rows < 16 { + 16 + } else { + n_real_rows.next_power_of_two() + }; + values.resize(padded_nb_rows * NUM_CPU_COLS, F::zero()); // Interpret values as a slice of arrays of length `NUM_CPU_COLS` let rows = unsafe { core::slice::from_raw_parts_mut( - values.as_mut_ptr().cast::<[F; NUM_CPU_COLS]>(), + values.as_mut_ptr() as *mut [F; NUM_CPU_COLS], values.len() / NUM_CPU_COLS, ) }; - rows[n_real_rows..].par_iter_mut().for_each(|padded_row| { + rows[n_real_rows..].iter_mut().for_each(|padded_row| { padded_row[CPU_COL_MAP.selectors.imm_b] = F::one(); padded_row[CPU_COL_MAP.selectors.imm_c] = F::one(); }); diff --git a/core/src/io.rs b/core/src/io.rs index ffffae0b2..6c761f5b9 100644 --- a/core/src/io.rs +++ b/core/src/io.rs @@ -45,7 +45,7 @@ impl SphinxStdin { } /// Read a value from the buffer. - pub fn read(&mut self) -> T { + pub fn read(&mut self) -> T { let result: T = bincode::deserialize(&self.buffer[self.ptr]).expect("failed to deserialize"); self.ptr += 1; @@ -127,7 +127,7 @@ impl SphinxPublicValues { } /// Write a value to the buffer. - pub fn write(&mut self, data: &T) { + pub fn write(&mut self, data: &T) { self.buffer.write(data); } diff --git a/core/src/lib.rs b/core/src/lib.rs index 74025dcf9..54db96faa 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -24,3 +24,10 @@ pub mod utils; #[allow(unused_imports)] use runtime::{Program, Runtime}; use stark::StarkGenericConfig; + +/// The global version for all components of SP1. +/// +/// This string should be updated whenever any step in verifying an SP1 proof changes, including +/// core, recursion, and plonk-bn254. This string is used to download SP1 artifacts and the gnark +/// docker image. +pub const SPHINX_CIRCUIT_VERSION: &str = "v1.0.7-testnet"; diff --git a/core/src/memory/global.rs b/core/src/memory/global.rs index ae11bad09..61e1f09eb 100644 --- a/core/src/memory/global.rs +++ b/core/src/memory/global.rs @@ -2,10 +2,12 @@ use core::borrow::{Borrow, BorrowMut}; use core::mem::size_of; use std::array; -use p3_air::{Air, AirBuilder, BaseAir}; -use p3_field::{AbstractField, PrimeField}; -use p3_matrix::{dense::RowMajorMatrix, Matrix}; -use p3_maybe_rayon::prelude::{ParallelBridge, ParallelIterator}; +use p3_air::BaseAir; +use p3_air::{Air, AirBuilder}; +use p3_field::AbstractField; +use p3_field::PrimeField; +use p3_matrix::dense::RowMajorMatrix; +use p3_matrix::Matrix; use sphinx_derive::AlignedBorrow; use super::MemoryInitializeFinalizeEvent; @@ -71,81 +73,61 @@ impl MachineAir for MemoryChip { MemoryChipType::Finalize => input.events().1, } .to_vec(); - memory_events.sort_by_key(|event| event.addr); - - let mut rows = vec![F::zero(); memory_events.len() * NUM_MEMORY_INIT_COLS]; - let chunk_size = std::cmp::max(memory_events.len() / num_cpus::get(), 1); - - rows.chunks_mut(chunk_size * NUM_MEMORY_INIT_COLS) - .enumerate() - .par_bridge() - .for_each(|(i, rows)| { - rows.chunks_mut(NUM_MEMORY_INIT_COLS) - .enumerate() - .for_each(|(j, row)| { - let idx = i * chunk_size + j; - - let MemoryInitializeFinalizeEvent { - addr, - value, - shard, - timestamp, - used, - } = memory_events[idx]; - - let cols: &mut MemoryInitCols = row.borrow_mut(); - cols.addr = F::from_canonical_u32(addr); - cols.addr_bits.populate(addr); - cols.shard = F::from_canonical_u32(shard); - cols.timestamp = F::from_canonical_u32(timestamp); - cols.value = array::from_fn(|i| F::from_canonical_u32((value >> i) & 1)); - cols.is_real = F::from_canonical_u32(used); - - if idx != memory_events.len() - 1 { - let next_addr = memory_events[idx + 1].addr; - assert_ne!(next_addr, addr); - - cols.addr_bits.populate(addr); - - cols.seen_diff_bits[0] = F::zero(); - for k in 0..32 { - let rev_k = 32 - k - 1; - let next_bit = ((next_addr >> rev_k) & 1) == 1; - let local_bit = ((addr >> rev_k) & 1) == 1; - cols.match_bits[k] = F::from_bool( - (local_bit && next_bit) || (!local_bit && !next_bit), - ); - cols.seen_diff_bits[k + 1] = cols.seen_diff_bits[k] - + (F::one() - cols.seen_diff_bits[k]) - * (F::one() - cols.match_bits[k]); - cols.not_match_and_not_seen_diff_bits[k] = (F::one() - - cols.match_bits[k]) - * (F::one() - cols.seen_diff_bits[k]); - } - assert_eq!( - cols.seen_diff_bits[cols.seen_diff_bits.len() - 1], - F::one() - ); - } - }); - }); - - let mut trace = RowMajorMatrix::new(rows, NUM_MEMORY_INIT_COLS); + let rows: Vec<[F; NUM_MEMORY_INIT_COLS]> = (0..memory_events.len()) // OPT: change this to par_iter + .map(|i| { + let MemoryInitializeFinalizeEvent { + addr, + value, + shard, + timestamp, + used, + } = memory_events[i]; + + let mut row = [F::zero(); NUM_MEMORY_INIT_COLS]; + let cols: &mut MemoryInitCols = row.as_mut_slice().borrow_mut(); + cols.addr = F::from_canonical_u32(addr); + cols.addr_bits.populate(addr); + cols.shard = F::from_canonical_u32(shard); + cols.timestamp = F::from_canonical_u32(timestamp); + cols.value = array::from_fn(|i| F::from_canonical_u32((value >> i) & 1)); + cols.is_real = F::from_canonical_u32(used); + + if i != memory_events.len() - 1 { + let next_addr = memory_events[i + 1].addr; + assert_ne!(next_addr, addr); + + cols.addr_bits.populate(addr); + + cols.seen_diff_bits[0] = F::zero(); + for j in 0..32 { + let rev_j = 32 - j - 1; + let next_bit = ((next_addr >> rev_j) & 1) == 1; + let local_bit = ((addr >> rev_j) & 1) == 1; + cols.match_bits[j] = + F::from_bool((local_bit && next_bit) || (!local_bit && !next_bit)); + cols.seen_diff_bits[j + 1] = cols.seen_diff_bits[j] + + (F::one() - cols.seen_diff_bits[j]) * (F::one() - cols.match_bits[j]); + cols.not_match_and_not_seen_diff_bits[j] = + (F::one() - cols.match_bits[j]) * (F::one() - cols.seen_diff_bits[j]); + } + assert_eq!(cols.seen_diff_bits[cols.seen_diff_bits.len() - 1], F::one()); + } + + row + }) + .collect::>(); + + let mut trace = RowMajorMatrix::new( + rows.into_iter().flatten().collect::>(), + NUM_MEMORY_INIT_COLS, + ); pad_to_power_of_two::(&mut trace.values); trace } - fn generate_dependencies>( - &self, - _input: &EL, - _output: &mut ExecutionRecord, - ) { - // Do nothing since this chip has no dependencies. - } - fn included(&self, shard: &Self::Record) -> bool { match self.kind { MemoryChipType::Initialize => !shard.memory_initialize_events.is_empty(), diff --git a/core/src/memory/program.rs b/core/src/memory/program.rs index 067d03b29..16298154a 100644 --- a/core/src/memory/program.rs +++ b/core/src/memory/program.rs @@ -1,4 +1,3 @@ -// TODO(wwared): Update this file to include MemoryProgram only in the first shard, see issue #38 use core::borrow::{Borrow, BorrowMut}; use core::mem::size_of; use p3_air::{Air, AirBuilder, AirBuilderWithPublicValues, BaseAir, PairBuilder}; @@ -38,7 +37,7 @@ pub struct MemoryProgramMultCols { /// This column is technically redundant with `is_real`, but it's included for clarity. pub multiplicity: T, - /// Columns to see if current shard is 1. + /// Whether the shard is the first shard. pub is_first_shard: IsZeroOperation, } @@ -83,7 +82,6 @@ impl MachineAir for MemoryProgramChip { cols.addr = F::from_canonical_u32(addr); cols.value = Word::from(word); cols.is_real = F::one(); - row }) .collect::>(); @@ -128,7 +126,7 @@ impl MachineAir for MemoryProgramChip { let mut row = [F::zero(); NUM_MEMORY_PROGRAM_MULT_COLS]; let cols: &mut MemoryProgramMultCols = row.as_mut_slice().borrow_mut(); cols.multiplicity = mult; - IsZeroOperation::populate(&mut cols.is_first_shard, input.index() - 1); + cols.is_first_shard.populate(input.index() - 1); row }) .collect::>(); @@ -179,25 +177,25 @@ where .collect::>(), ); + // Constrain `is_first_shard` to be 1 if and only if the shard is the first shard. IsZeroOperation::::eval( builder, - public_values.shard - AB::Expr::one(), + public_values.shard - AB::F::one(), mult_local.is_first_shard, prep_local.is_real.into(), ); - let is_first_shard = mult_local.is_first_shard.result; // Multiplicity must be either 0 or 1. builder.assert_bool(mult_local.multiplicity); // If first shard and preprocessed is real, multiplicity must be one. builder - .when(is_first_shard * prep_local.is_real) - .assert_one(mult_local.multiplicity); + .when(mult_local.is_first_shard.result) + .assert_eq(mult_local.multiplicity, prep_local.is_real.into()); - // If not first shard or preprocessed is not real, multiplicity must be zero. + // If it's not the first shard, then the multiplicity must be zero. builder - .when((AB::Expr::one() - is_first_shard) + (AB::Expr::one() - prep_local.is_real)) + .when_not(mult_local.is_first_shard.result) .assert_zero(mult_local.multiplicity); let mut values = vec![AB::Expr::zero(), AB::Expr::zero(), prep_local.addr.into()]; diff --git a/core/src/runtime/hooks.rs b/core/src/runtime/hooks.rs new file mode 100644 index 000000000..97951c0b5 --- /dev/null +++ b/core/src/runtime/hooks.rs @@ -0,0 +1,124 @@ +use std::collections::HashMap; + +use k256::ecdsa::{RecoveryId, Signature, VerifyingKey}; +use k256::elliptic_curve::ops::Invert; + +use super::Runtime; + +pub trait Hook: Fn(HookEnv<'_, '_>, &[u8]) -> Vec> + Send {} + +impl, &[u8]) -> Vec> + Send> Hook for F {} + +pub type BoxedHook<'a> = Box; + +/// The file descriptor through which to access `hook_ecrecover`. +pub const FD_ECRECOVER_HOOK: u32 = 5; + +/// A registry of hooks to call, indexed by the file descriptors through which they are accessed. +pub struct HookRegistry<'a> { + /// Table of registered hooks. Prefer using `Runtime::invoke_hook` and + /// `HookRegistry::register` over interacting with this field directly. + pub table: HashMap>, +} + +impl<'a> HookRegistry<'a> { + /// Create a registry with the default hooks. + pub fn new() -> Self { + Default::default() + } + + /// Create an empty registry. + pub fn empty() -> Self { + Self { + table: Default::default(), + } + } + + /// Register a hook under a given name. + pub fn register(&mut self, name: u32, hook: BoxedHook<'a>) { + self.table.insert(name, hook); + } +} + +impl<'a> Default for HookRegistry<'a> { + fn default() -> Self { + // When `LazyCell` gets stabilized (1.81.0), we can use it to avoid unnecessary allocations. + let table = { + let entries: Vec<(u32, BoxedHook<'_>)> = vec![ + // Note: To ensure any `fd` value is synced with `zkvm/precompiles/src/io.rs`, + // add an assertion to the test `hook_fds_match` below. + (FD_ECRECOVER_HOOK, Box::new(hook_ecrecover)), + ]; + HashMap::from_iter(entries) + }; + + Self { table } + } +} + +/// Environment that a hook may read from. +#[derive(Clone, Copy)] +pub struct HookEnv<'a, 'b> { + pub runtime: &'a Runtime<'b>, +} + +pub fn hook_ecrecover(_env: HookEnv<'_, '_>, buf: &[u8]) -> Vec> { + assert_eq!( + buf.len(), + 65 + 32, + "ecrecover input should have length 65 + 32" + ); + let (sig, msg_hash) = buf.split_at(65); + let sig: &[u8; 65] = sig.try_into().unwrap(); + let msg_hash: &[u8; 32] = msg_hash.try_into().unwrap(); + + let mut recovery_id = sig[64]; + let mut sig = Signature::from_slice(&sig[..64]).unwrap(); + + if let Some(sig_normalized) = sig.normalize_s() { + sig = sig_normalized; + recovery_id ^= 1 + }; + let recid = RecoveryId::from_byte(recovery_id).expect("Recovery ID is valid"); + + let recovered_key = VerifyingKey::recover_from_prehash(&msg_hash[..], &sig, recid).unwrap(); + let bytes = recovered_key.to_sec1_bytes(); + + let (_, s) = sig.split_scalars(); + let s_inverse = s.invert(); + + vec![bytes.to_vec(), s_inverse.to_bytes().to_vec()] +} + +#[cfg(test)] +pub(crate) mod tests { + use crate::{ + runtime::Program, + utils::{self, tests::ECRECOVER_ELF}, + }; + + use super::*; + + #[test] + pub(crate) fn hook_fds_match() { + use sphinx_zkvm::precompiles::io; + assert_eq!(FD_ECRECOVER_HOOK, io::FD_ECRECOVER_HOOK) + } + + #[test] + pub(crate) fn registry_new_is_inhabited() { + assert_ne!(HookRegistry::new().table.len(), 0); + } + + #[test] + pub(crate) fn registry_empty_is_empty() { + assert_eq!(HookRegistry::empty().table.len(), 0); + } + + #[test] + fn test_ecrecover_program_prove() { + utils::setup_logger(); + let program = Program::from(ECRECOVER_ELF); + utils::run_test(program).unwrap(); + } +} diff --git a/core/src/runtime/io.rs b/core/src/runtime/io.rs index 33897600d..a5c132d8c 100644 --- a/core/src/runtime/io.rs +++ b/core/src/runtime/io.rs @@ -8,14 +8,14 @@ use serde::Serialize; use super::Runtime; -impl Read for Runtime { +impl<'a> Read for Runtime<'a> { fn read(&mut self, buf: &mut [u8]) -> std::io::Result { self.read_public_values_slice(buf); Ok(buf.len()) } } -impl Runtime { +impl<'a> Runtime<'a> { pub fn write_stdin(&mut self, input: &T) { let mut buf = Vec::new(); bincode::serialize_into(&mut buf, input).expect("serialization failed"); diff --git a/core/src/runtime/mod.rs b/core/src/runtime/mod.rs index c5292ca56..d167a33cd 100644 --- a/core/src/runtime/mod.rs +++ b/core/src/runtime/mod.rs @@ -1,3 +1,4 @@ +mod hooks; mod instruction; mod io; mod memory; @@ -5,24 +6,28 @@ mod opcode; mod program; mod record; mod register; +mod report; mod state; mod syscall; #[macro_use] mod utils; +pub mod subproof; +pub use hooks::*; pub use instruction::*; pub use memory::*; pub use opcode::*; pub use program::*; pub use record::*; pub use register::*; +pub use report::ExecutionReport; pub(crate) use state::*; +use subproof::{DefaultSubproofVerifier, SubproofVerifier}; pub use syscall::*; pub use utils::*; use hashbrown::hash_map::Entry; use hashbrown::HashMap; -use std::fmt::{Display, Formatter, Result as FmtResult}; use std::fs::File; use std::io::BufWriter; use std::io::Write; @@ -44,7 +49,7 @@ use crate::{alu::AluEvent, cpu::CpuEvent}; /// /// For more information on the RV32IM instruction set, see the following: /// https://www.cs.sfu.ca/~ashriram/Courses/CS295/assets/notebooks/RISCV/RISCV_CARD.pdf -pub struct Runtime { +pub struct Runtime<'a> { /// The program. pub program: Arc, @@ -89,49 +94,13 @@ pub struct Runtime { pub report: ExecutionReport, /// Whether we should write to the report. - pub should_report: bool, -} - -#[derive(Default, Debug, Clone, PartialEq, Eq)] -pub struct ExecutionReport { - pub instruction_counts: HashMap, - pub syscall_counts: HashMap, -} - -impl ExecutionReport { - pub fn total_instruction_count(&self) -> u64 { - self.instruction_counts.values().sum() - } - - pub fn total_syscall_count(&self) -> u64 { - self.syscall_counts.values().sum() - } -} + pub print_report: bool, -impl Display for ExecutionReport { - fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { - writeln!(f, "Instruction Counts:")?; - let mut sorted_instructions = self.instruction_counts.iter().collect::>(); + /// Verifier used to sanity check `verify_sp1_proof` during runtime. + pub subproof_verifier: Arc, - // Sort instructions by opcode name - sorted_instructions.sort_by_key(|&(opcode, _)| opcode.to_string()); - for (opcode, count) in sorted_instructions { - writeln!(f, " {}: {}", opcode, count)?; - } - writeln!(f, "Total Instructions: {}", self.total_instruction_count())?; - - writeln!(f, "Syscall Counts:")?; - let mut sorted_syscalls = self.syscall_counts.iter().collect::>(); - - // Sort syscalls by syscall name - sorted_syscalls.sort_by_key(|&(syscall, _)| format!("{:?}", syscall)); - for (syscall, count) in sorted_syscalls { - writeln!(f, " {}: {}", syscall, count)?; - } - writeln!(f, "Total Syscall Count: {}", self.total_syscall_count())?; - - Ok(()) - } + /// Registry of hooks, to be invoked by writing to certain file descriptors. + pub hook_registry: HookRegistry<'a>, } #[derive(Error, Debug)] @@ -148,7 +117,7 @@ pub enum ExecutionError { Unimplemented(), } -impl Runtime { +impl<'a> Runtime<'a> { // Create a new runtime from a program. pub fn new(program: Program, opts: SphinxCoreOpts) -> Self { // Create a shared reference to the program. @@ -191,11 +160,24 @@ impl Runtime { syscall_map, emit_events: true, max_syscall_cycles, - report: Default::default(), - should_report: false, + report: ExecutionReport::default(), + print_report: false, + subproof_verifier: Arc::new(DefaultSubproofVerifier::new()), + hook_registry: HookRegistry::default(), } } + /// Invokes the hook corresponding to the given file descriptor `fd` with the data `buf`, + /// returning the resulting data. + pub fn hook(&self, fd: u32, buf: &[u8]) -> Vec> { + self.hook_registry.table[&fd](self.hook_env(), buf) + } + + /// Prepare a `HookEnv` for use by hooks. + pub fn hook_env(&self) -> HookEnv<'_, '_> { + HookEnv { runtime: self } + } + /// Recover runtime state from a program and existing execution state. pub fn recover(program: Program, state: ExecutionState, opts: SphinxCoreOpts) -> Self { let mut runtime = Self::new(program, opts); @@ -612,9 +594,9 @@ impl Runtime { let lookup_id = create_alu_lookup_id(); let syscall_lookup_id = create_alu_lookup_id(); - if self.should_report && !self.unconstrained { + if self.print_report && !self.unconstrained { self.report - .instruction_counts + .opcode_counts .entry(instruction.opcode) .and_modify(|c| *c += 1) .or_insert(1); @@ -834,7 +816,7 @@ impl Runtime { b = self.rr(Register::X10, MemoryAccessPosition::B); let syscall = SyscallCode::from_u32(syscall_id); - if self.should_report && !self.unconstrained { + if self.print_report && !self.unconstrained { self.report .syscall_counts .entry(syscall) @@ -1014,6 +996,7 @@ impl Runtime { /// Execute up to `self.shard_batch_size` cycles, returning the events emitted and whether the program ended. pub fn execute_record(&mut self) -> Result<(ExecutionRecord, bool), ExecutionError> { self.emit_events = true; + self.print_report = true; let done = self.execute()?; Ok((std::mem::take(&mut self.record), done)) } @@ -1021,6 +1004,7 @@ impl Runtime { /// Execute up to `self.shard_batch_size` cycles, returning a copy of the prestate and whether the program ended. pub fn execute_state(&mut self) -> Result<(ExecutionState, bool), ExecutionError> { self.emit_events = false; + self.print_report = false; let state = self.state.clone(); let done = self.execute()?; Ok((state, done)) @@ -1030,7 +1014,7 @@ impl Runtime { self.state.clk = 0; self.state.channel = 0; - tracing::info!("loading memory image"); + tracing::debug!("loading memory image"); for (addr, value) in self.program.memory_image.iter() { self.state.memory.insert( *addr, @@ -1046,20 +1030,18 @@ impl Runtime { self.record .memory_initialize_events .push(MemoryInitializeFinalizeEvent::initialize(0, 0, true)); - - tracing::info!("starting execution"); } pub fn run_untraced(&mut self) -> Result<(), ExecutionError> { self.emit_events = false; - self.should_report = true; + self.print_report = true; while !self.execute()? {} Ok(()) } pub fn run(&mut self) -> Result<(), ExecutionError> { self.emit_events = true; - self.should_report = true; + self.print_report = true; while !self.execute()? {} Ok(()) } @@ -1103,11 +1085,6 @@ impl Runtime { } fn postprocess(&mut self) { - tracing::info!( - "finished execution clk = {} pc = 0x{:x?}", - self.state.global_clk, - self.state.pc - ); // Flush remaining stdout/stderr for (fd, buf) in self.io_buf.iter() { if !buf.is_empty() { @@ -1128,6 +1105,12 @@ impl Runtime { buf.flush().unwrap(); } + // Ensure that all proofs and input bytes were read, otherwise warn the user. + assert!(self.state.proof_stream_ptr == self.state.proof_stream.len(), "Not all proofs were read. Proving will fail during recursion. Did you pass too many proofs in or forget to call verify_sp1_proof?"); + if self.state.input_stream_ptr != self.state.input_stream.len() { + log::warn!("Not all input bytes were read."); + } + // SECTION: Set up all MemoryInitializeFinalizeEvents needed for memory argument. let memory_finalize_events = &mut self.record.memory_finalize_events; @@ -1199,6 +1182,13 @@ pub mod tests { Program::from(PANIC_ELF) } + fn _assert_send() {} + + /// Runtime needs to be Send so we can use it across async calls. + fn _assert_runtime_is_send() { + _assert_send::>(); + } + #[test] fn test_simple_program_run() { let program = simple_program(); @@ -1207,58 +1197,6 @@ pub mod tests { assert_eq!(runtime.register(Register::X31), 42); } - #[test] - fn test_ssz_withdrawals_program_run_report() { - let program = ssz_withdrawals_program(); - let mut runtime = Runtime::new(program, SphinxCoreOpts::default()); - runtime.run().unwrap(); - assert_eq!(runtime.report, { - use super::Opcode::*; - use super::SyscallCode::*; - super::ExecutionReport { - instruction_counts: [ - (BEQ, 19867), - (JAL, 3921), - (SRL, 288860), - (MULHU, 1152), - (SUB, 10433), - (SB, 55807), - (LB, 10995), - (SLL, 257511), - (JALR, 19801), - (BGEU, 4487), - (ECALL, 2264), - (DIVU, 5), - (XOR, 241804), - (BGE, 393), - (SW, 239570), - (AND, 142566), - (LW, 146149), - (BNE, 42547), - (SLTU, 13270), - (BLT, 917), - (LBU, 32925), - (ADD, 511695), - (OR, 283019), - (AUIPC, 9933), - (MUL, 3735), - (BLTU, 39475), - ] - .into(), - syscall_counts: [ - (COMMIT_DEFERRED_PROOFS, 8), - (SHA_COMPRESS, 1091), - (WRITE, 65), - (HALT, 1), - (COMMIT, 8), - (SHA_EXTEND, 1091), - ] - .into(), - } - }); - assert_eq!(runtime.report.total_instruction_count(), 2383101); - } - #[test] #[should_panic] fn test_panic() { diff --git a/core/src/runtime/record.rs b/core/src/runtime/record.rs index ce2fb3789..5596e56b8 100644 --- a/core/src/runtime/record.rs +++ b/core/src/runtime/record.rs @@ -835,13 +835,10 @@ impl MachineRecord for ExecutionRecord { self.nonce_lookup.insert(event.lookup_id, i as u32); } - // Put the memory records in the last shard. - let last_shard = shards.last_mut().unwrap(); - - last_shard + first .memory_initialize_events .extend_from_slice(&self.memory_initialize_events); - last_shard + first .memory_finalize_events .extend_from_slice(&self.memory_finalize_events); diff --git a/core/src/runtime/report.rs b/core/src/runtime/report.rs new file mode 100644 index 000000000..0b602da13 --- /dev/null +++ b/core/src/runtime/report.rs @@ -0,0 +1,113 @@ +use std::collections::hash_map::Entry; +use std::collections::HashMap; +use std::fmt::{Display, Formatter, Result as FmtResult}; +use std::hash::Hash; +use std::ops::{Add, AddAssign}; + +use super::*; + +#[derive(Default, Debug, Clone, PartialEq, Eq)] +pub struct ExecutionReport { + pub opcode_counts: HashMap, + pub syscall_counts: HashMap, +} + +impl ExecutionReport { + /// Compute the total number of instructions run during the execution. + pub fn total_instruction_count(&self) -> u64 { + self.opcode_counts.values().sum() + } + + /// Compute the total number of syscalls made during the execution. + pub fn total_syscall_count(&self) -> u64 { + self.syscall_counts.values().sum() + } + + /// Returns sorted and formatted rows of a table of counts (e.g. `opcode_counts`). + /// + /// The table is sorted first by count (descending) and then by label (ascending). + /// The first column consists of the counts, is right-justified, and is padded precisely + /// enough to fit all the numbers. The second column consists of the labels (e.g. `OpCode`s). + /// The columns are separated by a single space character. + pub fn sorted_table_lines(table: &HashMap) -> Vec + where + K: Ord + Display, + V: Ord + Display, + { + // This function could be optimized here and there, + // for example by pre-allocating all `Vec`s, or by using less memory. + let mut lines = Vec::with_capacity(table.len()); + let mut entries = table.iter().collect::>(); + // Sort table by count (descending), then the name order (ascending). + entries.sort_unstable_by(|a, b| a.1.cmp(b.1).reverse().then_with(|| a.0.cmp(b.0))); + // Convert counts to `String`s to prepare them for printing and to measure their width. + let table_with_string_counts = entries + .into_iter() + .map(|(label, ct)| (label.to_string().to_lowercase(), ct.to_string())) + .collect::>(); + // Calculate width for padding the counts. + let width = table_with_string_counts + .first() + .map(|(_, b)| b.len()) + .unwrap_or_default(); + for (label, count) in table_with_string_counts { + lines.push(format!("{count:>width$} {label}")); + } + lines + } +} + +/// Combines two `HashMap`s together. If a key is in both maps, the values are added together. +fn hashmap_add_assign(lhs: &mut HashMap, rhs: HashMap) +where + K: Eq + Hash, + V: AddAssign, +{ + for (k, v) in rhs { + // Can't use `.and_modify(...).or_insert(...)` because we want to use `v` in both places. + match lhs.entry(k) { + Entry::Occupied(e) => *e.into_mut() += v, + Entry::Vacant(e) => drop(e.insert(v)), + } + } +} + +impl AddAssign for ExecutionReport { + fn add_assign(&mut self, rhs: Self) { + hashmap_add_assign(&mut self.opcode_counts, rhs.opcode_counts); + hashmap_add_assign(&mut self.syscall_counts, rhs.syscall_counts); + } +} + +impl Add for ExecutionReport { + type Output = Self; + + fn add(mut self, rhs: Self) -> Self::Output { + self += rhs; + self + } +} + +impl Display for ExecutionReport { + fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { + writeln!( + f, + "opcode counts ({} total instructions):", + self.total_instruction_count() + )?; + for line in Self::sorted_table_lines(&self.opcode_counts) { + writeln!(f, " {line}")?; + } + + writeln!( + f, + "syscall counts ({} total syscall instructions):", + self.total_syscall_count() + )?; + for line in Self::sorted_table_lines(&self.syscall_counts) { + writeln!(f, " {line}")?; + } + + Ok(()) + } +} diff --git a/core/src/runtime/subproof.rs b/core/src/runtime/subproof.rs new file mode 100644 index 000000000..701608646 --- /dev/null +++ b/core/src/runtime/subproof.rs @@ -0,0 +1,68 @@ +use std::sync::atomic::AtomicBool; + +use crate::{ + stark::{MachineVerificationError, ShardProof, StarkVerifyingKey}, + utils::BabyBearPoseidon2, +}; + +/// Verifier used in runtime when `sp1_zkvm::precompiles::verify::verify_sp1_proof` is called. This +/// is then used to sanity check that the user passed in the correct proof; the actual constraints +/// happen in the recursion layer. +/// +/// This needs to be passed in rather than written directly since the actual implementation relies +/// on crates in recursion that depend on sp1-core. +pub trait SubproofVerifier: Sync + Send { + fn verify_deferred_proof( + &self, + proof: &ShardProof, + vk: &StarkVerifyingKey, + vk_hash: [u32; 8], + committed_value_digest: [u32; 8], + ) -> Result<(), MachineVerificationError>; +} + +/// A dummy verifier which prints a warning on the first proof and does nothing else. +#[derive(Default)] +pub struct DefaultSubproofVerifier { + printed: AtomicBool, +} + +impl DefaultSubproofVerifier { + pub fn new() -> Self { + Self { + printed: AtomicBool::new(false), + } + } +} + +impl SubproofVerifier for DefaultSubproofVerifier { + fn verify_deferred_proof( + &self, + _proof: &ShardProof, + _vk: &StarkVerifyingKey, + _vk_hash: [u32; 8], + _committed_value_digest: [u32; 8], + ) -> Result<(), MachineVerificationError> { + if !self.printed.load(std::sync::atomic::Ordering::SeqCst) { + tracing::info!("Not verifying sub proof during runtime"); + self.printed + .store(true, std::sync::atomic::Ordering::SeqCst); + } + Ok(()) + } +} + +/// A dummy verifier which does nothing. +pub struct NoOpSubproofVerifier; + +impl SubproofVerifier for NoOpSubproofVerifier { + fn verify_deferred_proof( + &self, + _proof: &ShardProof, + _vk: &StarkVerifyingKey, + _vk_hash: [u32; 8], + _committed_value_digest: [u32; 8], + ) -> Result<(), MachineVerificationError> { + Ok(()) + } +} diff --git a/core/src/runtime/syscall.rs b/core/src/runtime/syscall.rs index 7dcfd1f02..8b6c68e59 100644 --- a/core/src/runtime/syscall.rs +++ b/core/src/runtime/syscall.rs @@ -36,7 +36,7 @@ use super::{ExecutionRecord, MemoryReadRecord, MemoryWriteRecord}; /// The syscall number is a 32-bit integer, with the following layout (in little-endian format) /// - The first byte is the syscall id. /// - The second byte is 0/1 depending on whether the syscall has a separate table. This is used -/// in the CPU table to determine whether to lookup the syscall using the syscall interaction. +/// in the CPU table to determine whether to lookup the syscall using the syscall interaction. /// - The third byte is the number of additional cycles the syscall uses. #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, EnumIter, Ord, PartialOrd)] #[allow(non_camel_case_types)] @@ -181,7 +181,7 @@ pub trait Syscall: Send + Sync { /// is that the return value is only for system calls such as `HALT`. Most precompiles use `arg1` /// and `arg2` to denote the addresses of the input data, and write the result to the memory at /// `arg1`. - fn execute(&self, ctx: &mut SyscallContext<'_>, arg1: u32, arg2: u32) -> Option; + fn execute(&self, ctx: &mut SyscallContext<'_, '_>, arg1: u32, arg2: u32) -> Option; /// The number of extra cycles that the syscall takes to execute. Unless this syscall is complex /// and requires many cycles, this should be zero. @@ -191,19 +191,19 @@ pub trait Syscall: Send + Sync { } /// A runtime for syscalls that is protected so that developers cannot arbitrarily modify the runtime. -pub struct SyscallContext<'a> { +pub struct SyscallContext<'a, 'b> { current_shard: u32, pub clk: u32, pub(crate) next_pc: u32, /// This is the exit_code used for the HALT syscall pub(crate) exit_code: u32, - pub(crate) rt: &'a mut Runtime, + pub(crate) rt: &'a mut Runtime<'b>, pub syscall_lookup_id: usize, } -impl<'a> SyscallContext<'a> { - pub fn new(runtime: &'a mut Runtime) -> Self { +impl<'a, 'b> SyscallContext<'a, 'b> { + pub fn new(runtime: &'a mut Runtime<'b>) -> Self { let current_shard = runtime.shard(); let clk = runtime.state.clk; Self { diff --git a/core/src/runtime/utils.rs b/core/src/runtime/utils.rs index 009353abb..41e132bcc 100644 --- a/core/src/runtime/utils.rs +++ b/core/src/runtime/utils.rs @@ -30,7 +30,7 @@ macro_rules! assert_valid_memory_access { }; } -impl Runtime { +impl<'a> Runtime<'a> { #[inline] pub fn log(&mut self, instruction: &Instruction) { // Write the current program counter to the trace buffer for the cycle tracer. diff --git a/core/src/stark/chip.rs b/core/src/stark/chip.rs index e48909a82..5e15a94dd 100644 --- a/core/src/stark/chip.rs +++ b/core/src/stark/chip.rs @@ -119,7 +119,7 @@ where pub fn generate_permutation_trace>( &self, preprocessed: Option<&RowMajorMatrix>, - main: &mut RowMajorMatrix, + main: &RowMajorMatrix, random_elements: &[EF], ) -> RowMajorMatrix where diff --git a/core/src/stark/machine.rs b/core/src/stark/machine.rs index b6ac32c8e..28891bad4 100644 --- a/core/src/stark/machine.rs +++ b/core/src/stark/machine.rs @@ -261,7 +261,7 @@ impl>> StarkMachine { // Display some statistics about the workload. let stats = record.stats(); - log::info!("shard: {:?}", stats); + log::debug!("shard: {:?}", stats); // For each chip, shard the events into segments. record.shard(config) diff --git a/core/src/stark/permutation.rs b/core/src/stark/permutation.rs index 809d25b6d..85d0a77e3 100644 --- a/core/src/stark/permutation.rs +++ b/core/src/stark/permutation.rs @@ -61,7 +61,7 @@ pub const fn permutation_trace_width(num_interactions: usize, batch_size: usize) /// /// The permutation trace has (N+1)*EF::NUM_COLS columns, where N is the number of interactions in /// the chip. -pub(crate) fn generate_permutation_trace>( +pub fn generate_permutation_trace>( sends: &[Interaction], receives: &[Interaction], preprocessed: Option<&RowMajorMatrix>, diff --git a/core/src/syscall/commit.rs b/core/src/syscall/commit.rs index c364020ff..4f074d4a3 100644 --- a/core/src/syscall/commit.rs +++ b/core/src/syscall/commit.rs @@ -18,7 +18,7 @@ impl Default for SyscallCommit { impl Syscall for SyscallCommit { fn execute( &self, - ctx: &mut SyscallContext<'_>, + ctx: &mut SyscallContext<'_, '_>, word_idx: u32, public_values_digest_word: u32, ) -> Option { @@ -47,7 +47,7 @@ impl Default for SyscallCommitDeferred { } impl Syscall for SyscallCommitDeferred { - fn execute(&self, ctx: &mut SyscallContext<'_>, word_idx: u32, word: u32) -> Option { + fn execute(&self, ctx: &mut SyscallContext<'_, '_>, word_idx: u32, word: u32) -> Option { let rt = &mut ctx.rt; rt.record.public_values.deferred_proofs_digest[word_idx as usize] = word; diff --git a/core/src/syscall/halt.rs b/core/src/syscall/halt.rs index 0e49d359e..7bf15b3bf 100644 --- a/core/src/syscall/halt.rs +++ b/core/src/syscall/halt.rs @@ -15,7 +15,7 @@ impl Default for SyscallHalt { } impl Syscall for SyscallHalt { - fn execute(&self, ctx: &mut SyscallContext<'_>, exit_code: u32, _: u32) -> Option { + fn execute(&self, ctx: &mut SyscallContext<'_, '_>, exit_code: u32, _: u32) -> Option { ctx.set_next_pc(0); ctx.set_exit_code(exit_code); None diff --git a/core/src/syscall/hint.rs b/core/src/syscall/hint.rs index da3c8828b..5d286bfbe 100644 --- a/core/src/syscall/hint.rs +++ b/core/src/syscall/hint.rs @@ -16,7 +16,7 @@ impl SyscallHintLen { } impl Syscall for SyscallHintLen { - fn execute(&self, ctx: &mut SyscallContext<'_>, _arg1: u32, _arg2: u32) -> Option { + fn execute(&self, ctx: &mut SyscallContext<'_, '_>, _arg1: u32, _arg2: u32) -> Option { assert!( ctx.rt.state.input_stream_ptr < ctx.rt.state.input_stream.len(), "not enough vecs in hint input stream" @@ -41,7 +41,7 @@ impl SyscallHintRead { } impl Syscall for SyscallHintRead { - fn execute(&self, ctx: &mut SyscallContext<'_>, ptr: u32, len: u32) -> Option { + fn execute(&self, ctx: &mut SyscallContext<'_, '_>, ptr: u32, len: u32) -> Option { assert!( ctx.rt.state.input_stream_ptr < ctx.rt.state.input_stream.len(), "not enough vecs in hint input stream" diff --git a/core/src/syscall/precompiles/bls12_381/g1_decompress.rs b/core/src/syscall/precompiles/bls12_381/g1_decompress.rs index 731398572..6b827fb17 100644 --- a/core/src/syscall/precompiles/bls12_381/g1_decompress.rs +++ b/core/src/syscall/precompiles/bls12_381/g1_decompress.rs @@ -84,7 +84,7 @@ pub struct Bls12381G1DecompressEvent { } pub fn create_bls12381_g1_decompress_event( - rt: &mut SyscallContext<'_>, + rt: &mut SyscallContext<'_, '_>, slice_ptr: u32, ) -> Bls12381G1DecompressEvent { let start_clk = rt.clk; @@ -132,7 +132,7 @@ pub fn create_bls12381_g1_decompress_event( } impl Syscall for Bls12381G1DecompressChip { - fn execute(&self, rt: &mut SyscallContext<'_>, arg1: u32, _arg2: u32) -> Option { + fn execute(&self, rt: &mut SyscallContext<'_, '_>, arg1: u32, _arg2: u32) -> Option { let event = create_bls12381_g1_decompress_event(rt, arg1); rt.record_mut().bls12381_g1_decompress_events.push(event); None diff --git a/core/src/syscall/precompiles/bls12_381/g2_add.rs b/core/src/syscall/precompiles/bls12_381/g2_add.rs index 8d78afc54..f9c2dd814 100644 --- a/core/src/syscall/precompiles/bls12_381/g2_add.rs +++ b/core/src/syscall/precompiles/bls12_381/g2_add.rs @@ -170,7 +170,7 @@ pub struct Bls12381G2AffineAddEvent { } impl Syscall for Bls12381G2AffineAddChip { - fn execute(&self, ctx: &mut SyscallContext<'_>, a_ptr: u32, b_ptr: u32) -> Option { + fn execute(&self, ctx: &mut SyscallContext<'_, '_>, a_ptr: u32, b_ptr: u32) -> Option { let clk = ctx.clk; let shard = ctx.current_shard(); let channel = ctx.current_channel(); diff --git a/core/src/syscall/precompiles/bls12_381/g2_double.rs b/core/src/syscall/precompiles/bls12_381/g2_double.rs index 7ea046cf2..f523fcf43 100644 --- a/core/src/syscall/precompiles/bls12_381/g2_double.rs +++ b/core/src/syscall/precompiles/bls12_381/g2_double.rs @@ -170,7 +170,7 @@ pub struct Bls12381G2AffineDoubleEvent { } impl Syscall for Bls12381G2AffineDoubleChip { - fn execute(&self, ctx: &mut SyscallContext<'_>, p_ptr: u32, _unused: u32) -> Option { + fn execute(&self, ctx: &mut SyscallContext<'_, '_>, p_ptr: u32, _unused: u32) -> Option { let clk = ctx.clk; let shard = ctx.current_shard(); let channel = ctx.current_channel(); diff --git a/core/src/syscall/precompiles/bls12_381/mod.rs b/core/src/syscall/precompiles/bls12_381/mod.rs index e7a03d345..182a5fe11 100644 --- a/core/src/syscall/precompiles/bls12_381/mod.rs +++ b/core/src/syscall/precompiles/bls12_381/mod.rs @@ -25,7 +25,7 @@ impl Syscall for FieldAddSyscall { 1 } - fn execute(&self, rt: &mut SyscallContext<'_>, arg1: u32, arg2: u32) -> Option { + fn execute(&self, rt: &mut SyscallContext<'_, '_>, arg1: u32, arg2: u32) -> Option { let event = create_fp_event::(rt, FieldOperation::Add, arg1, arg2); rt.record_mut().bls12381_fp_events.push(event); None @@ -37,7 +37,7 @@ impl Syscall for FieldSubSyscall { 1 } - fn execute(&self, rt: &mut SyscallContext<'_>, arg1: u32, arg2: u32) -> Option { + fn execute(&self, rt: &mut SyscallContext<'_, '_>, arg1: u32, arg2: u32) -> Option { let event = create_fp_event::(rt, FieldOperation::Sub, arg1, arg2); rt.record_mut().bls12381_fp_events.push(event); None @@ -49,7 +49,7 @@ impl Syscall for FieldMulSyscall { 1 } - fn execute(&self, rt: &mut SyscallContext<'_>, arg1: u32, arg2: u32) -> Option { + fn execute(&self, rt: &mut SyscallContext<'_, '_>, arg1: u32, arg2: u32) -> Option { let event = create_fp_event::(rt, FieldOperation::Mul, arg1, arg2); rt.record_mut().bls12381_fp_events.push(event); None @@ -61,7 +61,7 @@ impl Syscall for QuadFieldAddSyscall { 1 } - fn execute(&self, rt: &mut SyscallContext<'_>, arg1: u32, arg2: u32) -> Option { + fn execute(&self, rt: &mut SyscallContext<'_, '_>, arg1: u32, arg2: u32) -> Option { let event = create_fp2_event::(rt, QuadFieldOperation::Add, arg1, arg2); rt.record_mut().bls12381_fp2_events.push(event); None @@ -73,7 +73,7 @@ impl Syscall for QuadFieldSubSyscall { 1 } - fn execute(&self, rt: &mut SyscallContext<'_>, arg1: u32, arg2: u32) -> Option { + fn execute(&self, rt: &mut SyscallContext<'_, '_>, arg1: u32, arg2: u32) -> Option { let event = create_fp2_event::(rt, QuadFieldOperation::Sub, arg1, arg2); rt.record_mut().bls12381_fp2_events.push(event); None @@ -85,7 +85,7 @@ impl Syscall for QuadFieldMulSyscall { 1 } - fn execute(&self, rt: &mut SyscallContext<'_>, arg1: u32, arg2: u32) -> Option { + fn execute(&self, rt: &mut SyscallContext<'_, '_>, arg1: u32, arg2: u32) -> Option { let event = create_fp2_event::(rt, QuadFieldOperation::Mul, arg1, arg2); rt.record_mut().bls12381_fp2_events.push(event); None diff --git a/core/src/syscall/precompiles/edwards/ed_add.rs b/core/src/syscall/precompiles/edwards/ed_add.rs index 9e630806b..da5c6ae34 100644 --- a/core/src/syscall/precompiles/edwards/ed_add.rs +++ b/core/src/syscall/precompiles/edwards/ed_add.rs @@ -150,7 +150,7 @@ impl< 1 } - fn execute(&self, rt: &mut SyscallContext<'_>, arg1: u32, arg2: u32) -> Option { + fn execute(&self, rt: &mut SyscallContext<'_, '_>, arg1: u32, arg2: u32) -> Option { let event = create_ec_add_event::(rt, arg1, arg2); rt.record_mut().ed_add_events.push(event); None diff --git a/core/src/syscall/precompiles/edwards/ed_decompress.rs b/core/src/syscall/precompiles/edwards/ed_decompress.rs index 07dabdaa2..6446d301b 100644 --- a/core/src/syscall/precompiles/edwards/ed_decompress.rs +++ b/core/src/syscall/precompiles/edwards/ed_decompress.rs @@ -301,7 +301,7 @@ pub struct EdDecompressChip { impl, E: EdwardsParameters> Syscall for EdDecompressChip { - fn execute(&self, rt: &mut SyscallContext<'_>, arg1: u32, sign: u32) -> Option { + fn execute(&self, rt: &mut SyscallContext<'_, '_>, arg1: u32, sign: u32) -> Option { let start_clk = rt.clk; let slice_ptr = arg1; assert!(slice_ptr % 4 == 0, "Pointer must be 4-byte aligned."); diff --git a/core/src/syscall/precompiles/field/mod.rs b/core/src/syscall/precompiles/field/mod.rs index b53cb8ed6..dacec7b8b 100644 --- a/core/src/syscall/precompiles/field/mod.rs +++ b/core/src/syscall/precompiles/field/mod.rs @@ -103,7 +103,7 @@ impl<'a, FP: FieldParameters> WithEvents<'a> for FieldChip { } pub fn create_fp_event( - rt: &mut SyscallContext<'_>, + rt: &mut SyscallContext<'_, '_>, op: FieldOperation, arg1: u32, arg2: u32, diff --git a/core/src/syscall/precompiles/keccak256/execute.rs b/core/src/syscall/precompiles/keccak256/execute.rs index 17a9f4666..5b4dab795 100644 --- a/core/src/syscall/precompiles/keccak256/execute.rs +++ b/core/src/syscall/precompiles/keccak256/execute.rs @@ -19,7 +19,7 @@ impl Syscall for KeccakPermuteChip { 1 } - fn execute(&self, rt: &mut SyscallContext<'_>, arg1: u32, arg2: u32) -> Option { + fn execute(&self, rt: &mut SyscallContext<'_, '_>, arg1: u32, arg2: u32) -> Option { let start_clk = rt.clk; let state_ptr = arg1; assert!(arg2 == 0, "Expected arg2 to be 0, got {}", arg2); diff --git a/core/src/syscall/precompiles/mod.rs b/core/src/syscall/precompiles/mod.rs index e4046e58d..d85d25e4b 100644 --- a/core/src/syscall/precompiles/mod.rs +++ b/core/src/syscall/precompiles/mod.rs @@ -39,7 +39,7 @@ pub struct ECAddEvent { } pub fn create_ec_add_event( - rt: &mut SyscallContext<'_>, + rt: &mut SyscallContext<'_, '_>, arg1: u32, arg2: u32, ) -> ECAddEvent> { @@ -95,7 +95,7 @@ pub struct ECDoubleEvent { } pub fn create_ec_double_event( - rt: &mut SyscallContext<'_>, + rt: &mut SyscallContext<'_, '_>, arg1: u32, _: u32, ) -> ECDoubleEvent> { diff --git a/core/src/syscall/precompiles/quad_field/mod.rs b/core/src/syscall/precompiles/quad_field/mod.rs index bd021a812..95ecd2dfa 100644 --- a/core/src/syscall/precompiles/quad_field/mod.rs +++ b/core/src/syscall/precompiles/quad_field/mod.rs @@ -126,7 +126,7 @@ pub struct QuadFieldEvent { } pub fn create_fp2_event( - rt: &mut SyscallContext<'_>, + rt: &mut SyscallContext<'_, '_>, op: QuadFieldOperation, arg1: u32, arg2: u32, diff --git a/core/src/syscall/precompiles/secp256k1/decompress.rs b/core/src/syscall/precompiles/secp256k1/decompress.rs index 4e47d91aa..55fba4b43 100644 --- a/core/src/syscall/precompiles/secp256k1/decompress.rs +++ b/core/src/syscall/precompiles/secp256k1/decompress.rs @@ -80,7 +80,7 @@ pub struct Secp256k1DecompressEvent { } pub fn create_secp256k1_decompress_event( - rt: &mut SyscallContext<'_>, + rt: &mut SyscallContext<'_, '_>, slice_ptr: u32, is_odd: u32, ) -> Secp256k1DecompressEvent { @@ -122,7 +122,7 @@ pub fn create_secp256k1_decompress_event( } impl Syscall for Secp256k1DecompressChip { - fn execute(&self, rt: &mut SyscallContext<'_>, arg1: u32, arg2: u32) -> Option { + fn execute(&self, rt: &mut SyscallContext<'_, '_>, arg1: u32, arg2: u32) -> Option { let event = create_secp256k1_decompress_event(rt, arg1, arg2); rt.record_mut().secp256k1_decompress_events.push(event); None diff --git a/core/src/syscall/precompiles/sha256/compress/execute.rs b/core/src/syscall/precompiles/sha256/compress/execute.rs index 70d012b32..53ea5973b 100644 --- a/core/src/syscall/precompiles/sha256/compress/execute.rs +++ b/core/src/syscall/precompiles/sha256/compress/execute.rs @@ -12,7 +12,7 @@ impl Syscall for ShaCompressChip { 1 } - fn execute(&self, rt: &mut SyscallContext<'_>, arg1: u32, arg2: u32) -> Option { + fn execute(&self, rt: &mut SyscallContext<'_, '_>, arg1: u32, arg2: u32) -> Option { let w_ptr = arg1; let h_ptr = arg2; assert_ne!(w_ptr, h_ptr); @@ -76,9 +76,9 @@ impl Syscall for ShaCompressChip { } // Push the SHA extend event. + let lookup_id = rt.syscall_lookup_id; let shard = rt.current_shard(); let channel = rt.current_channel(); - let lookup_id = rt.syscall_lookup_id; rt.record_mut().sha_compress_events.push(ShaCompressEvent { lookup_id, shard, diff --git a/core/src/syscall/precompiles/sha256/extend/execute.rs b/core/src/syscall/precompiles/sha256/extend/execute.rs index c914e1bbd..4993142eb 100644 --- a/core/src/syscall/precompiles/sha256/extend/execute.rs +++ b/core/src/syscall/precompiles/sha256/extend/execute.rs @@ -9,7 +9,7 @@ impl Syscall for ShaExtendChip { 48 } - fn execute(&self, rt: &mut SyscallContext<'_>, arg1: u32, arg2: u32) -> Option { + fn execute(&self, rt: &mut SyscallContext<'_, '_>, arg1: u32, arg2: u32) -> Option { let clk_init = rt.clk; let w_ptr = arg1; assert!(arg2 == 0, "arg2 must be 0"); @@ -57,9 +57,9 @@ impl Syscall for ShaExtendChip { } // Push the SHA extend event. + let lookup_id = rt.syscall_lookup_id; let shard = rt.current_shard(); let channel = rt.current_channel(); - let lookup_id = rt.syscall_lookup_id; rt.record_mut().sha_extend_events.push(ShaExtendEvent { lookup_id, shard, diff --git a/core/src/syscall/precompiles/uint256/air.rs b/core/src/syscall/precompiles/uint256/air.rs new file mode 100644 index 000000000..8dad96c02 --- /dev/null +++ b/core/src/syscall/precompiles/uint256/air.rs @@ -0,0 +1,406 @@ +use crate::air::{BaseAirBuilder, MachineAir, Polynomial, SphinxAirBuilder, WORD_SIZE}; +use crate::bytes::event::ByteRecord; +use crate::memory::{value_as_limbs, MemoryReadCols, MemoryWriteCols}; +use crate::operations::field::field_op::{FieldOpCols, FieldOperation}; +use crate::operations::field::params::NumWords; +use crate::operations::field::params::{Limbs, NumLimbs}; +use crate::operations::IsZeroOperation; +use crate::runtime::{ExecutionRecord, Program, Syscall, SyscallCode}; +use crate::runtime::{MemoryReadRecord, MemoryWriteRecord}; +use crate::stark::MachineRecord; +use crate::syscall::precompiles::SyscallContext; +use crate::utils::ec::uint256::U256Field; +use crate::utils::{ + bytes_to_words_le, limbs_from_access, limbs_from_prev_access, pad_rows, words_to_bytes_le, + words_to_bytes_le_vec, +}; +use generic_array::GenericArray; +use num::Zero; +use num::{BigUint, One}; +use p3_air::AirBuilder; +use p3_air::{Air, BaseAir}; +use p3_field::AbstractField; +use p3_field::PrimeField32; +use p3_matrix::dense::RowMajorMatrix; +use p3_matrix::Matrix; +use serde::{Deserialize, Serialize}; +use sphinx_derive::AlignedBorrow; +use std::borrow::{Borrow, BorrowMut}; +use std::mem::size_of; +use typenum::Unsigned; + +/// The number of columns in the Uint256MulCols. +const NUM_COLS: usize = size_of::>(); + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Uint256MulEvent { + pub lookup_id: usize, + pub shard: u32, + pub channel: u32, + pub clk: u32, + pub x_ptr: u32, + pub x: Vec, + pub y_ptr: u32, + pub y: Vec, + pub modulus: Vec, + pub x_memory_records: Vec, + pub y_memory_records: Vec, + pub modulus_memory_records: Vec, +} + +#[derive(Default)] +pub struct Uint256MulChip; + +impl Uint256MulChip { + pub const fn new() -> Self { + Self + } +} + +type WordsFieldElement = ::WordsFieldElement; +const WORDS_FIELD_ELEMENT: usize = WordsFieldElement::USIZE; + +/// A set of columns for the Uint256Mul operation. +#[derive(Debug, Clone, AlignedBorrow)] +#[repr(C)] +pub struct Uint256MulCols { + /// The shard number of the syscall. + pub shard: T, + + /// The byte lookup channel. + pub channel: T, + + /// The clock cycle of the syscall. + pub clk: T, + + /// The none of the operation. + pub nonce: T, + + /// The pointer to the first input. + pub x_ptr: T, + + /// The pointer to the second input, which contains the y value and the modulus. + pub y_ptr: T, + + // Memory columns. + // x_memory is written to with the result, which is why it is of type MemoryWriteCols. + pub x_memory: GenericArray, WordsFieldElement>, + pub y_memory: GenericArray, WordsFieldElement>, + pub modulus_memory: GenericArray, WordsFieldElement>, + + // Columns for checking if modulus is zero. If it's zero, then use 2^256 as the effective modulus. + pub modulus_is_zero: IsZeroOperation, + + // Output values. We compute (x * y) % modulus. + pub output: FieldOpCols, + + pub is_real: T, +} + +impl MachineAir for Uint256MulChip { + type Record = ExecutionRecord; + type Program = Program; + + fn name(&self) -> String { + "Uint256MulMod".to_string() + } + + fn generate_trace( + &self, + input: &ExecutionRecord, + output: &mut ExecutionRecord, + ) -> RowMajorMatrix { + // Generate the trace rows & corresponding records for each chunk of events concurrently. + let rows_and_records = input + .uint256_mul_events + .chunks(1) + .map(|events| { + let mut records = ExecutionRecord::default(); + let mut new_byte_lookup_events = Vec::new(); + + let rows = events + .iter() + .map(|event| { + let mut row: [F; NUM_COLS] = [F::zero(); NUM_COLS]; + let cols: &mut Uint256MulCols = row.as_mut_slice().borrow_mut(); + + // Decode uint256 points + let x = BigUint::from_bytes_le(&words_to_bytes_le::<32>(&event.x)); + let y = BigUint::from_bytes_le(&words_to_bytes_le::<32>(&event.y)); + let modulus = + BigUint::from_bytes_le(&words_to_bytes_le::<32>(&event.modulus)); + + // Assign basic values to the columns. + cols.is_real = F::one(); + cols.shard = F::from_canonical_u32(event.shard); + cols.channel = F::from_canonical_u32(event.channel); + cols.clk = F::from_canonical_u32(event.clk); + cols.x_ptr = F::from_canonical_u32(event.x_ptr); + cols.y_ptr = F::from_canonical_u32(event.y_ptr); + + // Populate memory columns. + for i in 0..WORDS_FIELD_ELEMENT { + cols.x_memory[i].populate( + event.channel, + event.x_memory_records[i], + &mut new_byte_lookup_events, + ); + cols.y_memory[i].populate( + event.channel, + event.y_memory_records[i], + &mut new_byte_lookup_events, + ); + cols.modulus_memory[i].populate( + event.channel, + event.modulus_memory_records[i], + &mut new_byte_lookup_events, + ); + } + + let modulus_bytes = words_to_bytes_le_vec(&event.modulus); + let modulus_byte_sum = modulus_bytes.iter().map(|b| *b as u32).sum::(); + IsZeroOperation::populate(&mut cols.modulus_is_zero, modulus_byte_sum); + + // Populate the output column. + let effective_modulus = if modulus.is_zero() { + BigUint::one() << 256 + } else { + modulus.clone() + }; + cols.output.populate_with_modulus( + &mut new_byte_lookup_events, + event.shard, + event.channel, + &x, + &y, + &effective_modulus, + // &modulus, + FieldOperation::Mul, + ); + + row + }) + .collect::>(); + records.add_byte_lookup_events(new_byte_lookup_events); + (rows, records) + }) + .collect::>(); + + // Generate the trace rows for each event. + let mut rows = Vec::new(); + for (row, mut record) in rows_and_records { + rows.extend(row); + output.append(&mut record); + } + + pad_rows(&mut rows, || { + let mut row: [F; NUM_COLS] = [F::zero(); NUM_COLS]; + let cols: &mut Uint256MulCols = row.as_mut_slice().borrow_mut(); + + let x = BigUint::zero(); + let y = BigUint::zero(); + cols.output + .populate(&mut vec![], 0, 0, &x, &y, FieldOperation::Mul); + + row + }); + + // Convert the trace to a row major matrix. + let mut trace = + RowMajorMatrix::new(rows.into_iter().flatten().collect::>(), NUM_COLS); + + // Write the nonces to the trace. + for i in 0..trace.height() { + let cols: &mut Uint256MulCols = + trace.values[i * NUM_COLS..(i + 1) * NUM_COLS].borrow_mut(); + cols.nonce = F::from_canonical_usize(i); + } + + trace + } + + fn included(&self, shard: &Self::Record) -> bool { + !shard.uint256_mul_events.is_empty() + } +} + +impl Syscall for Uint256MulChip { + fn num_extra_cycles(&self) -> u32 { + 0 + } + + fn execute(&self, rt: &mut SyscallContext, arg1: u32, arg2: u32) -> Option { + let x_ptr = arg1; + if x_ptr % 4 != 0 { + panic!(); + } + let y_ptr = arg2; + if y_ptr % 4 != 0 { + panic!(); + } + + // First read the words for the x value. We can read a slice_unsafe here because we write + // the computed result to x later. + let x = rt.slice_unsafe(x_ptr, WORDS_FIELD_ELEMENT); + + // Read the y value. + let (y_memory_records, y) = rt.mr_slice(y_ptr, WORDS_FIELD_ELEMENT); + + // The modulus is stored after the y value. We increment the pointer by the number of words. + let modulus_ptr = y_ptr + WORDS_FIELD_ELEMENT as u32 * WORD_SIZE as u32; + let (modulus_memory_records, modulus) = rt.mr_slice(modulus_ptr, WORDS_FIELD_ELEMENT); + + // Get the BigUint values for x, y, and the modulus. + let uint256_x = BigUint::from_bytes_le(&words_to_bytes_le_vec(&x)); + let uint256_y = BigUint::from_bytes_le(&words_to_bytes_le_vec(&y)); + let uint256_modulus = BigUint::from_bytes_le(&words_to_bytes_le_vec(&modulus)); + + // Perform the multiplication and take the result modulo the modulus. + let result: BigUint = if uint256_modulus.is_zero() { + let modulus = BigUint::one() << 256; + (uint256_x * uint256_y) % modulus + } else { + (uint256_x * uint256_y) % uint256_modulus + }; + + let mut result_bytes = result.to_bytes_le(); + result_bytes.resize(32, 0u8); // Pad the result to 32 bytes. + + // Convert the result to little endian u32 words. + let result = bytes_to_words_le::<8>(&result_bytes); + + // Write the result to x and keep track of the memory records. + let x_memory_records = rt.mw_slice(x_ptr, &result); + + let lookup_id = rt.syscall_lookup_id; + let shard = rt.current_shard(); + let channel = rt.current_channel(); + let clk = rt.clk; + rt.record_mut().uint256_mul_events.push(Uint256MulEvent { + lookup_id, + shard, + channel, + clk, + x_ptr, + x, + y_ptr, + y, + modulus, + x_memory_records, + y_memory_records, + modulus_memory_records, + }); + + None + } +} + +impl BaseAir for Uint256MulChip { + fn width(&self) -> usize { + NUM_COLS + } +} + +impl Air for Uint256MulChip +where + AB: SphinxAirBuilder, + Limbs::Limbs>: Copy, +{ + fn eval(&self, builder: &mut AB) { + let main = builder.main(); + let local = main.row_slice(0); + let local: &Uint256MulCols = (*local).borrow(); + let next = main.row_slice(1); + let next: &Uint256MulCols = (*next).borrow(); + + // Constrain the incrementing nonce. + builder.when_first_row().assert_zero(local.nonce); + builder + .when_transition() + .assert_eq(local.nonce + AB::Expr::one(), next.nonce); + + // We are computing (x * y) % modulus. The value of x is stored in the "prev_value" of + // the x_memory, since we write to it later. + let x_limbs = limbs_from_prev_access(&local.x_memory); + let y_limbs = limbs_from_access(&local.y_memory); + let modulus_limbs = limbs_from_access(&local.modulus_memory); + + // If the modulus is zero, then we don't perform the modulus operation. + // Evaluate the modulus_is_zero operation by summing each byte of the modulus. The sum will + // not overflow because we are summing 32 bytes. + let modulus_byte_sum = modulus_limbs + .0 + .iter() + .fold(AB::Expr::zero(), |acc, &limb| acc + limb); + IsZeroOperation::::eval( + builder, + modulus_byte_sum, + local.modulus_is_zero, + local.is_real.into(), + ); + + // If the modulus is zero, we'll actually use 2^256 as the modulus, so nothing happens. + // Otherwise, we use the modulus passed in. + let modulus_is_zero = local.modulus_is_zero.result; + let mut coeff_2_256 = Vec::new(); + coeff_2_256.resize(32, AB::Expr::zero()); + coeff_2_256.push(AB::Expr::one()); + let modulus_polynomial: Polynomial = modulus_limbs.into(); + let p_modulus: Polynomial = modulus_polynomial + * (AB::Expr::one() - modulus_is_zero.into()) + + Polynomial::from_coefficients(&coeff_2_256) * modulus_is_zero.into(); + + // Evaluate the uint256 multiplication + local.output.eval_with_modulus( + builder, + &x_limbs, + &y_limbs, + &p_modulus, + FieldOperation::Mul, + local.shard, + local.channel, + local.is_real, + ); + + // Assert that the correct result is being written to x_memory. + builder + .when(local.is_real) + .assert_all_eq(local.output.result, value_as_limbs(&local.x_memory)); + + // Read and write x. + builder.eval_memory_access_slice( + local.shard, + local.channel, + local.clk.into(), + local.x_ptr, + &local.x_memory, + local.is_real, + ); + + // Evaluate the y_ptr memory access. We concatenate y and modulus into a single array since + // we read it contiguously from the y_ptr memory location. + builder.eval_memory_access_slice( + local.shard, + local.channel, + local.clk.into(), + local.y_ptr, + &[local.y_memory, local.modulus_memory].concat(), + local.is_real, + ); + + // Receive the arguments. + builder.receive_syscall( + local.shard, + local.channel, + local.clk, + local.nonce, + AB::F::from_canonical_u32(SyscallCode::UINT256_MUL.syscall_id()), + local.x_ptr, + local.y_ptr, + local.is_real, + ); + + // Assert that is_real is a boolean. + builder.assert_bool(local.is_real); + } +} diff --git a/core/src/syscall/precompiles/uint256/mod.rs b/core/src/syscall/precompiles/uint256/mod.rs new file mode 100644 index 000000000..aeb42cc60 --- /dev/null +++ b/core/src/syscall/precompiles/uint256/mod.rs @@ -0,0 +1,31 @@ +mod air; + +pub use air::*; + +#[cfg(test)] +mod tests { + + use crate::operations::field::params::FieldParameters; + use crate::{ + io::SphinxStdin, + runtime::Program, + utils::{ + self, + ec::{uint256::U256Field, utils::biguint_from_limbs}, + run_test_io, + tests::UINT256_MUL_ELF, + }, + }; + + #[test] + fn test_uint256_mul() { + utils::setup_logger(); + let program = Program::from(UINT256_MUL_ELF); + run_test_io(program, SphinxStdin::new()).unwrap(); + } + + #[test] + fn test_uint256_modulus() { + assert_eq!(biguint_from_limbs(U256Field::MODULUS), U256Field::modulus()); + } +} diff --git a/core/src/syscall/precompiles/weierstrass/weierstrass_decompress.rs b/core/src/syscall/precompiles/weierstrass/weierstrass_decompress.rs new file mode 100644 index 000000000..3c4c6dc2b --- /dev/null +++ b/core/src/syscall/precompiles/weierstrass/weierstrass_decompress.rs @@ -0,0 +1,455 @@ +use core::borrow::{Borrow, BorrowMut}; +use core::mem::size_of; +use std::fmt::Debug; + +use generic_array::GenericArray; +use num::BigUint; +use num::Zero; +use p3_air::{Air, AirBuilder, BaseAir}; +use p3_field::AbstractField; +use p3_field::PrimeField32; +use p3_matrix::dense::RowMajorMatrix; +use p3_matrix::Matrix; +use sphinx_derive::AlignedBorrow; +use std::marker::PhantomData; +use typenum::Unsigned; + +use crate::air::BaseAirBuilder; +use crate::air::MachineAir; +use crate::air::SphinxAirBuilder; +use crate::bytes::event::ByteRecord; +use crate::memory::MemoryReadCols; +use crate::memory::MemoryReadWriteCols; +use crate::operations::field::field_op::FieldOpCols; +use crate::operations::field::field_op::FieldOperation; +use crate::operations::field::field_sqrt::FieldSqrtCols; +use crate::operations::field::params::{FieldParameters, NumWords}; +use crate::operations::field::params::{Limbs, NumLimbs}; +use crate::operations::field::range::FieldRangeCols; +use crate::runtime::ExecutionRecord; +use crate::runtime::Program; +use crate::runtime::Syscall; +use crate::runtime::SyscallCode; +use crate::syscall::precompiles::create_ec_decompress_event; +use crate::syscall::precompiles::SyscallContext; +use crate::utils::ec::weierstrass::bls12_381::bls12381_sqrt; +use crate::utils::ec::weierstrass::secp256k1::secp256k1_sqrt; +use crate::utils::ec::weierstrass::WeierstrassParameters; +use crate::utils::ec::CurveType; +use crate::utils::ec::EllipticCurve; +use crate::utils::limbs_from_access; +use crate::utils::limbs_from_prev_access; +use crate::utils::{bytes_to_words_le_vec, pad_rows}; + +pub const fn num_weierstrass_decompress_cols() -> usize { + size_of::>() +} + +/// A set of columns to compute `WeierstrassDecompress` that decompresses a point on a Weierstrass +/// curve. +#[derive(Debug, Clone, AlignedBorrow)] +#[repr(C)] +pub struct WeierstrassDecompressCols { + pub is_real: T, + pub shard: T, + pub channel: T, + pub clk: T, + pub nonce: T, + pub ptr: T, + pub is_odd: T, + pub x_access: GenericArray, P::WordsFieldElement>, + pub y_access: GenericArray, P::WordsFieldElement>, + pub(crate) range_x: FieldRangeCols, + pub(crate) x_2: FieldOpCols, + pub(crate) x_3: FieldOpCols, + pub(crate) x_3_plus_b: FieldOpCols, + pub(crate) y: FieldSqrtCols, + pub(crate) neg_y: FieldOpCols, +} + +#[derive(Default)] +pub struct WeierstrassDecompressChip { + _marker: PhantomData, +} + +impl Syscall for WeierstrassDecompressChip { + fn execute(&self, rt: &mut SyscallContext, arg1: u32, arg2: u32) -> Option { + let event = create_ec_decompress_event::(rt, arg1, arg2); + match E::CURVE_TYPE { + CurveType::Secp256k1 => rt.record_mut().k256_decompress_events.push(event), + CurveType::Bls12381 => rt.record_mut().bls12381_decompress_events.push(event), + _ => panic!("Unsupported curve"), + } + None + } + + fn num_extra_cycles(&self) -> u32 { + 0 + } +} + +impl WeierstrassDecompressChip { + pub const fn new() -> Self { + Self { + _marker: PhantomData::, + } + } + + fn populate_field_ops( + record: &mut impl ByteRecord, + shard: u32, + channel: u32, + cols: &mut WeierstrassDecompressCols, + x: BigUint, + ) { + // Y = sqrt(x^3 + b) + cols.range_x.populate(record, shard, channel, &x); + let x_2 = cols.x_2.populate( + record, + shard, + channel, + &x.clone(), + &x.clone(), + FieldOperation::Mul, + ); + let x_3 = cols + .x_3 + .populate(record, shard, channel, &x_2, &x, FieldOperation::Mul); + let b = E::b_int(); + let x_3_plus_b = + cols.x_3_plus_b + .populate(record, shard, channel, &x_3, &b, FieldOperation::Add); + + let sqrt_fn = match E::CURVE_TYPE { + CurveType::Secp256k1 => secp256k1_sqrt, + CurveType::Bls12381 => bls12381_sqrt, + _ => panic!("Unsupported curve"), + }; + let y = cols + .y + .populate(record, shard, channel, &x_3_plus_b, sqrt_fn); + + let zero = BigUint::zero(); + cols.neg_y + .populate(record, shard, channel, &zero, &y, FieldOperation::Sub); + } +} + +impl MachineAir + for WeierstrassDecompressChip +{ + type Record = ExecutionRecord; + type Program = Program; + + fn name(&self) -> String { + match E::CURVE_TYPE { + CurveType::Secp256k1 => "Secp256k1Decompress".to_string(), + CurveType::Bls12381 => "Bls12381Decompress".to_string(), + _ => panic!("Unsupported curve"), + } + } + + fn generate_trace( + &self, + input: &ExecutionRecord, + output: &mut ExecutionRecord, + ) -> RowMajorMatrix { + let events = match E::CURVE_TYPE { + CurveType::Secp256k1 => &input.k256_decompress_events, + CurveType::Bls12381 => &input.bls12381_decompress_events, + _ => panic!("Unsupported curve"), + }; + + let mut rows = Vec::new(); + + let mut new_byte_lookup_events = Vec::new(); + + for i in 0..events.len() { + let event = events[i].clone(); + let mut row = vec![F::zero(); num_weierstrass_decompress_cols::()]; + let cols: &mut WeierstrassDecompressCols = + row.as_mut_slice().borrow_mut(); + + cols.is_real = F::from_bool(true); + cols.shard = F::from_canonical_u32(event.shard); + cols.channel = F::from_canonical_u32(event.channel); + cols.channel = F::from_canonical_u32(event.channel); + cols.clk = F::from_canonical_u32(event.clk); + cols.ptr = F::from_canonical_u32(event.ptr); + cols.is_odd = F::from_canonical_u32(event.is_odd as u32); + + let x = BigUint::from_bytes_le(&event.x_bytes); + Self::populate_field_ops( + &mut new_byte_lookup_events, + event.shard, + event.channel, + cols, + x, + ); + + for i in 0..cols.x_access.len() { + cols.x_access[i].populate( + event.channel, + event.x_memory_records[i], + &mut new_byte_lookup_events, + ); + } + for i in 0..cols.y_access.len() { + cols.y_access[i].populate_write( + event.channel, + event.y_memory_records[i], + &mut new_byte_lookup_events, + ); + } + + rows.push(row); + } + output.add_byte_lookup_events(new_byte_lookup_events); + + pad_rows(&mut rows, || { + let mut row = vec![F::zero(); num_weierstrass_decompress_cols::()]; + let cols: &mut WeierstrassDecompressCols = + row.as_mut_slice().borrow_mut(); + + // take X of the generator as a dummy value to make sure Y^2 = X^3 + b holds + let dummy_value = E::generator().0; + let dummy_bytes = dummy_value.to_bytes_le(); + let words = bytes_to_words_le_vec(&dummy_bytes); + for i in 0..cols.x_access.len() { + cols.x_access[i].access.value = words[i].into(); + } + + Self::populate_field_ops(&mut vec![], 0, 0, cols, dummy_value); + row + }); + + let mut trace = RowMajorMatrix::new( + rows.into_iter().flatten().collect::>(), + num_weierstrass_decompress_cols::(), + ); + + // Write the nonces to the trace. + for i in 0..trace.height() { + let cols: &mut WeierstrassDecompressCols = trace.values[i + * num_weierstrass_decompress_cols::() + ..(i + 1) * num_weierstrass_decompress_cols::()] + .borrow_mut(); + cols.nonce = F::from_canonical_usize(i); + } + + trace + } + + fn included(&self, shard: &Self::Record) -> bool { + match E::CURVE_TYPE { + CurveType::Secp256k1 => !shard.k256_decompress_events.is_empty(), + CurveType::Bls12381 => !shard.bls12381_decompress_events.is_empty(), + _ => panic!("Unsupported curve"), + } + } +} + +impl BaseAir for WeierstrassDecompressChip { + fn width(&self) -> usize { + num_weierstrass_decompress_cols::() + } +} + +impl Air for WeierstrassDecompressChip +where + AB: SphinxAirBuilder, + Limbs::Limbs>: Copy, +{ + fn eval(&self, builder: &mut AB) { + let main = builder.main(); + let local = main.row_slice(0); + let local: &WeierstrassDecompressCols = (*local).borrow(); + let next = main.row_slice(1); + let next: &WeierstrassDecompressCols = (*next).borrow(); + + // Constrain the incrementing nonce. + builder.when_first_row().assert_zero(local.nonce); + builder + .when_transition() + .assert_eq(local.nonce + AB::Expr::one(), next.nonce); + + let num_limbs = ::Limbs::USIZE; + let num_words_field_element = num_limbs / 4; + + builder.assert_bool(local.is_odd); + + let x: Limbs::Limbs> = + limbs_from_prev_access(&local.x_access); + local + .range_x + .eval(builder, &x, local.shard, local.channel, local.is_real); + local.x_2.eval( + builder, + &x, + &x, + FieldOperation::Mul, + local.shard, + local.channel, + local.is_real, + ); + local.x_3.eval( + builder, + &local.x_2.result, + &x, + FieldOperation::Mul, + local.shard, + local.channel, + local.is_real, + ); + let b = E::b_int(); + let b_const = E::BaseField::to_limbs_field::(&b); + local.x_3_plus_b.eval( + builder, + &local.x_3.result, + &b_const, + FieldOperation::Add, + local.shard, + local.channel, + local.is_real, + ); + + local.neg_y.eval( + builder, + &[AB::Expr::zero()].iter(), + &local.y.multiplication.result, + FieldOperation::Sub, + local.shard, + local.channel, + local.is_real, + ); + + // Interpret the lowest bit of Y as whether it is odd or not. + let y_is_odd = local.y.lsb; + + local.y.eval( + builder, + &local.x_3_plus_b.result, + local.y.lsb, + local.shard, + local.channel, + local.is_real, + ); + + let y_limbs: Limbs::Limbs> = + limbs_from_access(&local.y_access); + builder + .when(local.is_real) + .when_ne(y_is_odd, AB::Expr::one() - local.is_odd) + .assert_all_eq(local.y.multiplication.result, y_limbs); + builder + .when(local.is_real) + .when_ne(y_is_odd, local.is_odd) + .assert_all_eq(local.neg_y.result, y_limbs); + + for i in 0..num_words_field_element { + builder.eval_memory_access( + local.shard, + local.channel, + local.clk, + local.ptr.into() + AB::F::from_canonical_u32((i as u32) * 4 + num_limbs as u32), + &local.x_access[i], + local.is_real, + ); + } + for i in 0..num_words_field_element { + builder.eval_memory_access( + local.shard, + local.channel, + local.clk, + local.ptr.into() + AB::F::from_canonical_u32((i as u32) * 4), + &local.y_access[i], + local.is_real, + ); + } + + let syscall_id = match E::CURVE_TYPE { + CurveType::Secp256k1 => { + AB::F::from_canonical_u32(SyscallCode::SECP256K1_DECOMPRESS.syscall_id()) + } + CurveType::Bls12381 => { + AB::F::from_canonical_u32(SyscallCode::BLS12381_DECOMPRESS.syscall_id()) + } + _ => panic!("Unsupported curve"), + }; + + builder.receive_syscall( + local.shard, + local.channel, + local.clk, + local.nonce, + syscall_id, + local.ptr, + local.is_odd, + local.is_real, + ); + } +} + +#[cfg(test)] +mod tests { + use crate::io::SphinxStdin; + use crate::utils::{self, tests::BLS12381_DECOMPRESS_ELF}; + use crate::Program; + use amcl::bls381::bls381::basic::key_pair_generate_g2; + use amcl::bls381::bls381::utils::deserialize_g1; + use amcl::rand::RAND; + use elliptic_curve::sec1::ToEncodedPoint; + use rand::{thread_rng, Rng}; + + use crate::utils::run_test_io; + use crate::utils::tests::SECP256K1_DECOMPRESS_ELF; + + #[test] + fn test_weierstrass_bls_decompress() { + utils::setup_logger(); + let mut rng = thread_rng(); + let mut rand = RAND::new(); + + let len = 100; + let random_slice = (0..len).map(|_| rng.gen::()).collect::>(); + rand.seed(len, &random_slice); + let (_, compressed) = key_pair_generate_g2(&mut RAND::new()); + + let stdin = SphinxStdin::from(&compressed); + let mut public_values = run_test_io(Program::from(BLS12381_DECOMPRESS_ELF), stdin).unwrap(); + + let mut result = [0; 96]; + public_values.read_slice(&mut result); + + let point = deserialize_g1(&compressed).unwrap(); + let x = point.getx().to_string(); + let y = point.gety().to_string(); + let decompressed = hex::decode(format!("{x}{y}")).unwrap(); + assert_eq!(result, decompressed.as_slice()); + } + + #[test] + fn test_weierstrass_k256_decompress() { + utils::setup_logger(); + + let mut rng = thread_rng(); + + let num_tests = 10; + + for _ in 0..num_tests { + let secret_key = k256::SecretKey::random(&mut rng); + let public_key = secret_key.public_key(); + let encoded = public_key.to_encoded_point(false); + let decompressed = encoded.as_bytes(); + let compressed = public_key.to_sec1_bytes(); + + let inputs = SphinxStdin::from(&compressed); + + let mut public_values = + run_test_io(Program::from(SECP256K1_DECOMPRESS_ELF), inputs).unwrap(); + let mut result = [0; 65]; + public_values.read_slice(&mut result); + assert_eq!(result, decompressed); + } + } +} diff --git a/core/src/syscall/unconstrained.rs b/core/src/syscall/unconstrained.rs index 291a9d610..22d0a6cc3 100644 --- a/core/src/syscall/unconstrained.rs +++ b/core/src/syscall/unconstrained.rs @@ -11,7 +11,7 @@ impl SyscallEnterUnconstrained { } impl Syscall for SyscallEnterUnconstrained { - fn execute(&self, ctx: &mut SyscallContext<'_>, _: u32, _: u32) -> Option { + fn execute(&self, ctx: &mut SyscallContext<'_, '_>, _: u32, _: u32) -> Option { assert!( !ctx.rt.unconstrained, "Unconstrained block is already active." @@ -40,7 +40,7 @@ impl SyscallExitUnconstrained { } impl Syscall for SyscallExitUnconstrained { - fn execute(&self, ctx: &mut SyscallContext<'_>, _: u32, _: u32) -> Option { + fn execute(&self, ctx: &mut SyscallContext<'_, '_>, _: u32, _: u32) -> Option { // Reset the state of the runtime. if ctx.rt.unconstrained { ctx.rt.state.global_clk = ctx.rt.unconstrained_state.global_clk; diff --git a/core/src/syscall/verify.rs b/core/src/syscall/verify.rs index 257fb5e39..233afa3d2 100644 --- a/core/src/syscall/verify.rs +++ b/core/src/syscall/verify.rs @@ -1,8 +1,4 @@ -use crate::{ - runtime::{Syscall, SyscallContext}, - stark::StarkGenericConfig, - utils::BabyBearPoseidon2Inner, -}; +use crate::runtime::{Syscall, SyscallContext}; /// Verifies an SP1 recursive verifier proof. Note that this syscall only verifies the proof during /// runtime. The actual constraint-level verification is deferred to the recursive layer, where @@ -22,10 +18,9 @@ impl Default for SyscallVerifySphinxProof { } impl Syscall for SyscallVerifySphinxProof { - #[allow(unused_variables, unused_mut)] fn execute( &self, - ctx: &mut SyscallContext<'_>, + ctx: &mut SyscallContext<'_, '_>, vkey_ptr: u32, pv_digest_ptr: u32, ) -> Option { @@ -44,11 +39,27 @@ impl Syscall for SyscallVerifySphinxProof { .map(|i| rt.word(pv_digest_ptr + i * 4)) .collect::>(); - let (proof, proof_vk) = &rt.state.proof_stream[rt.state.proof_stream_ptr]; + let proof_index = rt.state.proof_stream_ptr; + assert!( + proof_index < rt.state.proof_stream.len(), + "Not enough proofs were written to the runtime." + ); + let (proof, proof_vk) = &rt.state.proof_stream[proof_index].clone(); rt.state.proof_stream_ptr += 1; - let config = BabyBearPoseidon2Inner::new(); - let mut challenger = config.challenger(); + let vkey_bytes: [u32; 8] = vkey.try_into().unwrap(); + let pv_digest_bytes: [u32; 8] = pv_digest.try_into().unwrap(); + + ctx.rt + .subproof_verifier + .verify_deferred_proof(proof, proof_vk, vkey_bytes, pv_digest_bytes) + .unwrap_or_else(|e| { + panic!( + "Failed to verify proof {proof_index} with digest {}: {}", + hex::encode(bytemuck::cast_slice(&pv_digest_bytes)), + e + ) + }); None } diff --git a/core/src/syscall/write.rs b/core/src/syscall/write.rs index b70174b87..08c0ff1cf 100644 --- a/core/src/syscall/write.rs +++ b/core/src/syscall/write.rs @@ -18,72 +18,76 @@ impl Default for SyscallWrite { } impl Syscall for SyscallWrite { - fn execute(&self, ctx: &mut SyscallContext<'_>, arg1: u32, arg2: u32) -> Option { + fn execute(&self, ctx: &mut SyscallContext<'_, '_>, arg1: u32, arg2: u32) -> Option { let a2 = Register::X12; let rt = &mut ctx.rt; let fd = arg1; - if fd == 1 || fd == 2 || fd == 3 || fd == 4 { - let write_buf = arg2; - let nbytes = rt.register(a2); - // Read nbytes from memory starting at write_buf. - let bytes = (0..nbytes) - .map(|i| rt.byte(write_buf + i)) - .collect::>(); - let slice = bytes.as_slice(); - if fd == 1 { - let s = core::str::from_utf8(slice).unwrap(); - if s.contains("cycle-tracker-start:") { - let fn_name = s - .split("cycle-tracker-start:") - .last() - .unwrap() - .trim_end() - .trim_start(); - let depth = rt.cycle_tracker.len() as u32; - rt.cycle_tracker - .insert(fn_name.to_string(), (rt.state.global_clk, depth)); - let padding = (0..depth).map(|_| "│ ").collect::(); - log::debug!("{}┌╴{}", padding, fn_name); - } else if s.contains("cycle-tracker-end:") { - let fn_name = s - .split("cycle-tracker-end:") - .last() - .unwrap() - .trim_end() - .trim_start(); - let (start, depth) = rt.cycle_tracker.remove(fn_name).unwrap_or((0, 0)); - // Leftpad by 2 spaces for each depth. - let padding = (0..depth).map(|_| "│ ").collect::(); - log::info!( - "{}└╴{} cycles", - padding, - num_to_comma_separated(rt.state.global_clk - start) - ); - } else { - let flush_s = update_io_buf(ctx, fd, s); + let write_buf = arg2; + let nbytes = rt.register(a2); + // Read nbytes from memory starting at write_buf. + let bytes = (0..nbytes) + .map(|i| rt.byte(write_buf + i)) + .collect::>(); + let slice = bytes.as_slice(); + if fd == 1 { + let s = core::str::from_utf8(slice).unwrap(); + if s.contains("cycle-tracker-start:") { + let fn_name = s + .split("cycle-tracker-start:") + .last() + .unwrap() + .trim_end() + .trim_start(); + let depth = rt.cycle_tracker.len() as u32; + rt.cycle_tracker + .insert(fn_name.to_string(), (rt.state.global_clk, depth)); + let padding = (0..depth).map(|_| "│ ").collect::(); + log::debug!("{}┌╴{}", padding, fn_name); + } else if s.contains("cycle-tracker-end:") { + let fn_name = s + .split("cycle-tracker-end:") + .last() + .unwrap() + .trim_end() + .trim_start(); + let (start, depth) = rt.cycle_tracker.remove(fn_name).unwrap_or((0, 0)); + // Leftpad by 2 spaces for each depth. + let padding = (0..depth).map(|_| "│ ").collect::(); + log::info!( + "{}└╴{} cycles", + padding, + num_to_comma_separated(rt.state.global_clk - start) + ); + } else { + let flush_s = update_io_buf(ctx, fd, s); + if !flush_s.is_empty() { for line in flush_s { - println!("stdout: {line}"); + println!("stdout: {}", line); } } - } else if fd == 2 { - let s = core::str::from_utf8(slice).unwrap(); - let flush_s = update_io_buf(ctx, fd, s); + } + } else if fd == 2 { + let s = core::str::from_utf8(slice).unwrap(); + let flush_s = update_io_buf(ctx, fd, s); + if !flush_s.is_empty() { for line in flush_s { - println!("stderr: {line}"); + println!("stderr: {}", line); } - } else if fd == 3 { - rt.state.public_values_stream.extend_from_slice(slice); - } else if fd == 4 { - rt.state.input_stream.push(slice.to_vec()); - } else { - unreachable!() } + } else if fd == 3 { + rt.state.public_values_stream.extend_from_slice(slice); + } else if fd == 4 { + rt.state.input_stream.push(slice.to_vec()); + } else if let Some(hook) = rt.hook_registry.table.get(&fd) { + rt.state.input_stream.extend(hook(rt.hook_env(), slice)); + } else { + log::warn!("tried to write to unknown file descriptor {fd}"); } None } } -pub fn update_io_buf(ctx: &mut SyscallContext<'_>, fd: u32, s: &str) -> Vec { +pub fn update_io_buf(ctx: &mut SyscallContext<'_, '_>, fd: u32, s: &str) -> Vec { let rt = &mut ctx.rt; let entry = rt.io_buf.entry(fd).or_default(); entry.push_str(s); diff --git a/core/src/utils/ec/weierstrass/bls12_381.rs b/core/src/utils/ec/weierstrass/bls12_381.rs index 4606edb6e..8adbe0b34 100644 --- a/core/src/utils/ec/weierstrass/bls12_381.rs +++ b/core/src/utils/ec/weierstrass/bls12_381.rs @@ -230,7 +230,7 @@ impl WeierstrassParameters for Bls12381Parameters { impl Syscall for WeierstrassAddAssignChip { fn execute( &self, - rt: &mut crate::runtime::SyscallContext<'_>, + rt: &mut crate::runtime::SyscallContext<'_, '_>, arg1: u32, arg2: u32, ) -> Option { @@ -246,7 +246,7 @@ impl Syscall for WeierstrassAddAssignChip { impl Syscall for WeierstrassDoubleAssignChip { fn execute( &self, - rt: &mut crate::runtime::SyscallContext<'_>, + rt: &mut crate::runtime::SyscallContext<'_, '_>, arg1: u32, arg2: u32, ) -> Option { diff --git a/core/src/utils/ec/weierstrass/bn254.rs b/core/src/utils/ec/weierstrass/bn254.rs index 3550da138..aac794038 100644 --- a/core/src/utils/ec/weierstrass/bn254.rs +++ b/core/src/utils/ec/weierstrass/bn254.rs @@ -59,7 +59,7 @@ impl EllipticCurveParameters for Bn254Parameters { impl Syscall for WeierstrassAddAssignChip { fn execute( &self, - rt: &mut crate::runtime::SyscallContext<'_>, + rt: &mut crate::runtime::SyscallContext<'_, '_>, arg1: u32, arg2: u32, ) -> Option { @@ -76,7 +76,7 @@ impl Syscall for WeierstrassAddAssignChip { impl Syscall for WeierstrassDoubleAssignChip { fn execute( &self, - rt: &mut crate::runtime::SyscallContext<'_>, + rt: &mut crate::runtime::SyscallContext<'_, '_>, arg1: u32, arg2: u32, ) -> Option { diff --git a/core/src/utils/ec/weierstrass/secp256k1.rs b/core/src/utils/ec/weierstrass/secp256k1.rs index 3f3d9087d..54e4d2158 100644 --- a/core/src/utils/ec/weierstrass/secp256k1.rs +++ b/core/src/utils/ec/weierstrass/secp256k1.rs @@ -96,7 +96,7 @@ impl WeierstrassParameters for Secp256k1Parameters { impl Syscall for WeierstrassAddAssignChip { fn execute( &self, - rt: &mut crate::runtime::SyscallContext<'_>, + rt: &mut crate::runtime::SyscallContext<'_, '_>, arg1: u32, arg2: u32, ) -> Option { @@ -113,7 +113,7 @@ impl Syscall for WeierstrassAddAssignChip { impl Syscall for WeierstrassDoubleAssignChip { fn execute( &self, - rt: &mut crate::runtime::SyscallContext<'_>, + rt: &mut crate::runtime::SyscallContext<'_, '_>, arg1: u32, arg2: u32, ) -> Option { diff --git a/core/src/utils/mod.rs b/core/src/utils/mod.rs index 3666d44dd..d2d8fbbff 100644 --- a/core/src/utils/mod.rs +++ b/core/src/utils/mod.rs @@ -4,6 +4,7 @@ mod config; pub mod ec; mod logger; mod options; +#[cfg(any(test, feature = "programs"))] mod programs; mod prove; mod tracer; diff --git a/core/src/utils/options.rs b/core/src/utils/options.rs index 3fd292a35..f7d3b4394 100644 --- a/core/src/utils/options.rs +++ b/core/src/utils/options.rs @@ -43,6 +43,7 @@ impl SphinxCoreOpts { pub fn recursion() -> Self { let mut opts = Self::default(); opts.reconstruct_commitments = false; + opts.shard_size = DEFAULT_SHARD_SIZE; opts } } diff --git a/core/src/utils/programs.rs b/core/src/utils/programs.rs index d59ee7a86..132f6c5cf 100644 --- a/core/src/utils/programs.rs +++ b/core/src/utils/programs.rs @@ -1,4 +1,4 @@ -#[cfg(test)] +#![allow(unused)] pub mod tests { /// Demos. diff --git a/core/src/utils/prove.rs b/core/src/utils/prove.rs index 1f0438aa0..7d22dd69c 100644 --- a/core/src/utils/prove.rs +++ b/core/src/utils/prove.rs @@ -3,6 +3,7 @@ use nohash_hasher::BuildNoHashHasher; use std::fs::File; use std::io; use std::io::{Seek, Write}; +use std::sync::Arc; use web_time::Instant; pub use baby_bear_blake3::BabyBearBlake3; @@ -15,8 +16,9 @@ use thiserror::Error; use crate::air::MachineAir; use crate::io::{SphinxPublicValues, SphinxStdin}; use crate::lookup::InteractionBuilder; +use crate::runtime::subproof::{DefaultSubproofVerifier, NoOpSubproofVerifier, SubproofVerifier}; use crate::runtime::ExecutionError; -use crate::runtime::{ExecutionRecord, MemoryRecord, ShardingConfig}; +use crate::runtime::{ExecutionRecord, ExecutionReport, MemoryRecord, ShardingConfig}; use crate::stark::DebugConstraintBuilder; use crate::stark::Indexed; use crate::stark::MachineProof; @@ -46,7 +48,7 @@ pub enum SphinxCoreProverError { pub fn prove_simple( config: SC, - runtime: Runtime, + runtime: Runtime<'_>, ) -> Result, SphinxCoreProverError> where SC::Challenger: Clone, @@ -90,6 +92,24 @@ pub fn prove( config: SC, opts: SphinxCoreOpts, ) -> Result<(MachineProof, Vec), SphinxCoreProverError> +where + SC::Challenger: Clone, + OpeningProof: Send + Sync, + Com: Send + Sync, + PcsProverData: Send + Sync, + ShardMainData: Serialize + DeserializeOwned, + ::Val: PrimeField32, +{ + prove_with_subproof_verifier::(program, stdin, config, opts, &None) +} + +pub fn prove_with_subproof_verifier( + program: &Program, + stdin: &SphinxStdin, + config: SC, + opts: SphinxCoreOpts, + subproof_verifier: &Option>, +) -> Result<(MachineProof, Vec), SphinxCoreProverError> where SC::Challenger: Clone, OpeningProof: Send + Sync, @@ -106,6 +126,9 @@ where for proof in stdin.proofs.iter() { runtime.write_proof(proof.0.clone(), proof.1.clone()); } + if let Some(deferred_fn) = subproof_verifier.clone() { + runtime.subproof_verifier = deferred_fn; + } // Setup the machine. let machine = RiscvAir::machine(config); @@ -134,8 +157,8 @@ where let mut checkpoints = Vec::new(); let (public_values_stream, public_values) = loop { // Execute the runtime until we reach a checkpoint. - let (checkpoint, done) = runtime - .execute_state() + let (checkpoint, done) = tracing::info_span!("collect_checkpoints") + .in_scope(|| runtime.execute_state()) .map_err(SphinxCoreProverError::ExecutionError)?; // Save the checkpoint to a temp file. @@ -164,8 +187,9 @@ where let mut shard_main_datas = Vec::new(); let mut challenger = machine.config().challenger(); vk.observe_into(&mut challenger); - for checkpoint_file in checkpoints.iter_mut() { - let mut record = trace_checkpoint(program, checkpoint_file, opts); + for (num, checkpoint_file) in checkpoints.iter_mut().enumerate() { + let (mut record, _) = tracing::info_span!("commit_checkpoint", num) + .in_scope(|| trace_checkpoint(program, checkpoint_file, opts)); record.public_values = public_values; reset_seek(&mut *checkpoint_file); @@ -187,9 +211,12 @@ where // For each checkpoint, generate events and shard again, then prove the shards. let mut shard_proofs = Vec::>::new(); - for mut checkpoint_file in checkpoints { + let mut report_aggregate = ExecutionReport::default(); + for (num, mut checkpoint_file) in checkpoints.into_iter().enumerate() { let checkpoint_shards = { - let mut events = trace_checkpoint(program, &checkpoint_file, opts); + let (mut events, report) = tracing::info_span!("prove_checkpoint", num) + .in_scope(|| trace_checkpoint(program, &checkpoint_file, opts)); + report_aggregate += report; events.public_values = public_values; reset_seek(&mut checkpoint_file); tracing::debug_span!("shard").in_scope(|| machine.shard(events, &sharding_config)) @@ -217,6 +244,23 @@ where .collect::>(); shard_proofs.append(&mut checkpoint_proofs); } + // Log some of the `ExecutionReport` information. + tracing::info!( + "execution report (totals): total_cycles={}, total_syscall_cycles={}", + report_aggregate.total_instruction_count(), + report_aggregate.total_syscall_count() + ); + // Print the opcode and syscall count tables like `du`: + // sorted by count (descending) and with the count in the first column. + tracing::info!("execution report (opcode counts):"); + for line in ExecutionReport::sorted_table_lines(&report_aggregate.opcode_counts) { + tracing::info!(" {line}"); + } + tracing::info!("execution report (syscall counts):"); + for line in ExecutionReport::sorted_table_lines(&report_aggregate.syscall_counts) { + tracing::info!(" {line}"); + } + let proof = MachineProof:: { shard_proofs }; // Print the summary. @@ -281,7 +325,7 @@ pub fn run_test( #[allow(unused_variables)] pub fn run_test_core( - runtime: Runtime, + runtime: Runtime<'_>, ) -> Result< MachineProof, crate::stark::MachineVerificationError, @@ -345,13 +389,20 @@ where Ok(proof) } -fn trace_checkpoint(program: &Program, file: &File, opts: SphinxCoreOpts) -> ExecutionRecord { +fn trace_checkpoint( + program: &Program, + file: &File, + opts: SphinxCoreOpts, +) -> (ExecutionRecord, ExecutionReport) { let mut reader = io::BufReader::new(file); let state = bincode::deserialize_from(&mut reader).expect("failed to deserialize state"); let mut runtime = Runtime::recover(program.clone(), state, opts); + // We already passed the deferred proof verifier when creating checkpoints, so the proofs were + // already verified. So here we use a noop verifier to not print any warnings. + runtime.subproof_verifier = Arc::new(NoOpSubproofVerifier); let (events, _) = tracing::debug_span!("runtime.trace").in_scope(|| runtime.execute_record().unwrap()); - events + (events, runtime.report) } fn reset_seek(file: &mut File) { diff --git a/deny.toml b/deny.toml index 2af4fe167..bd2babee3 100644 --- a/deny.toml +++ b/deny.toml @@ -142,10 +142,10 @@ default = "deny" confidence-threshold = 0.8 # Allow 1 or more licenses on a per-crate basis, so that particular licenses # aren't accepted for every possible crate as with the normal allow list -exceptions = [ - # Each entry is the crate and version constraint, and its specific allow - # list -] +[[licenses.exceptions]] +allow = ["MPL-2.0"] +name = "webpki-roots" +version = "0.26.3" # Some crates don't have (easily) machine readable licensing information, # adding a clarification entry for it allows you to manually specify the @@ -203,7 +203,6 @@ license-files = [ { path = "COPYING", hash = 0x106164e0 } ] - [licenses.private] # If true, ignores workspace crates that aren't published, or are only # published to private registries. diff --git a/examples/Cargo.toml b/examples/Cargo.toml new file mode 100644 index 000000000..aa22c9bf0 --- /dev/null +++ b/examples/Cargo.toml @@ -0,0 +1,17 @@ +[workspace] +members = [ + "aggregation/script", + "bls12381-pairing/script", + "chess/script", + "cycle-tracking/script", + "fibonacci/script", + "io/script", + "is-prime/script", + "json/lib", + "json/script", + "regex/script", + "rsa/script", + "ssz-withdrawals/script", + "tendermint/script", +] +resolver = "2" \ No newline at end of file diff --git a/examples/aggregation/program/Cargo.lock b/examples/aggregation/program/Cargo.lock index f848f83f8..e8b96c158 100644 --- a/examples/aggregation/program/Cargo.lock +++ b/examples/aggregation/program/Cargo.lock @@ -617,6 +617,7 @@ dependencies = [ "cfg-if", "getrandom", "k256", + "lazy_static", "once_cell", "p3-baby-bear", "p3-field", diff --git a/examples/aggregation/program/elf/riscv32im-succinct-zkvm-elf b/examples/aggregation/program/elf/riscv32im-succinct-zkvm-elf index 6e6679a3c..d04c69b56 100755 Binary files a/examples/aggregation/program/elf/riscv32im-succinct-zkvm-elf and b/examples/aggregation/program/elf/riscv32im-succinct-zkvm-elf differ diff --git a/examples/aggregation/script/Cargo.lock b/examples/aggregation/script/Cargo.lock index 82b6ca924..4e0e98baf 100644 --- a/examples/aggregation/script/Cargo.lock +++ b/examples/aggregation/script/Cargo.lock @@ -630,16 +630,16 @@ dependencies = [ [[package]] name = "blake3" -version = "1.5.1" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30cca6d3674597c30ddf2c587bf8d9d65c9a84d2326d941cc79c9842dfe0ef52" +checksum = "e9ec96fe9a81b5e365f9db71fe00edc4fe4ca2cc7dcb7861f0603012a7caa210" dependencies = [ "arrayref", "arrayvec", "cc", "cfg-if", "constant_time_eq", - "rayon", + "rayon-core", ] [[package]] @@ -699,6 +699,12 @@ version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" +[[package]] +name = "bytemuck" +version = "1.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e" + [[package]] name = "byteorder" version = "1.5.0" @@ -1622,21 +1628,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "form_urlencoded" version = "1.2.1" @@ -2090,19 +2081,21 @@ dependencies = [ ] [[package]] -name = "hyper-tls" -version = "0.6.0" +name = "hyper-rustls" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" dependencies = [ - "bytes", - "http-body-util", + "futures-util", + "http 1.1.0", "hyper 1.3.1", "hyper-util", - "native-tls", + "rustls", + "rustls-pki-types", "tokio", - "tokio-native-tls", + "tokio-rustls", "tower-service", + "webpki-roots", ] [[package]] @@ -2317,7 +2310,7 @@ checksum = "6971da4d9c3aa03c3d8f3ff0f4155b534aad021292003895a469716b2a230378" dependencies = [ "base64 0.21.7", "pem", - "ring", + "ring 0.16.20", "serde", "serde_json", "simple_asn1", @@ -2512,24 +2505,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "native-tls" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" -dependencies = [ - "lazy_static", - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - [[package]] name = "nohash-hasher" version = "0.2.0" @@ -2754,50 +2729,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "openssl" -version = "0.10.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" -dependencies = [ - "bitflags 2.5.0", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.60", -] - -[[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "openssl-sys" -version = "0.9.102" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "overload" version = "0.1.1" @@ -3400,6 +3331,53 @@ version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" +[[package]] +name = "quinn" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4ceeeeabace7857413798eb1ffa1e9c905a9946a57d81fb69b4b71c4d8eb3ad" +dependencies = [ + "bytes", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "quinn-proto" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddf517c03a109db8100448a4be38d498df8a210a99fe0e1b9eaf39e78c640efe" +dependencies = [ + "bytes", + "rand", + "ring 0.17.8", + "rustc-hash", + "rustls", + "slab", + "thiserror", + "tinyvec", + "tracing", +] + +[[package]] +name = "quinn-udp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9096629c45860fc7fb143e125eb826b5e721e10be3263160c7d60ca832cf8c46" +dependencies = [ + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.52.0", +] + [[package]] name = "quote" version = "1.0.36" @@ -3586,23 +3564,25 @@ dependencies = [ "http-body 1.0.0", "http-body-util", "hyper 1.3.1", - "hyper-tls", + "hyper-rustls", "hyper-util", "ipnet", "js-sys", "log", "mime", - "native-tls", "once_cell", "percent-encoding", "pin-project-lite", + "quinn", + "rustls", "rustls-pemfile", + "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper 1.0.1", "tokio", - "tokio-native-tls", + "tokio-rustls", "tokio-util", "tower-service", "url", @@ -3610,6 +3590,7 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", + "webpki-roots", "winreg 0.52.0", ] @@ -3648,11 +3629,26 @@ dependencies = [ "libc", "once_cell", "spin 0.5.2", - "untrusted", + "untrusted 0.7.1", "web-sys", "winapi", ] +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin 0.9.8", + "untrusted 0.9.0", + "windows-sys 0.52.0", +] + [[package]] name = "ripemd" version = "0.1.3" @@ -3773,6 +3769,20 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rustls" +version = "0.23.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebbbdb961df0ad3f2652da8f3fdc4b36122f568f968f45ad3316f26c025c677b" +dependencies = [ + "once_cell", + "ring 0.17.8", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + [[package]] name = "rustls-pemfile" version = "2.1.2" @@ -3789,6 +3799,17 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "beb461507cee2c2ff151784c52762cf4d9ff6a61f3e80968600ed24fa837fa54" +[[package]] +name = "rustls-webpki" +version = "0.102.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3bce581c0dd41bce533ce695a1437fa16a7ab5ac3ccfa99fe1a620a7885eabf" +dependencies = [ + "ring 0.17.8", + "rustls-pki-types", + "untrusted 0.9.0", +] + [[package]] name = "rustversion" version = "1.0.15" @@ -3864,15 +3885,6 @@ dependencies = [ "sdd", ] -[[package]] -name = "schannel" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" -dependencies = [ - "windows-sys 0.52.0", -] - [[package]] name = "scopeguard" version = "1.2.0" @@ -3911,29 +3923,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "security-framework" -version = "2.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "770452e37cad93e0a50d5abc3990d2bc351c36d0328f86cefec2f2fb206eaef6" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f3cc463c0ef97e11c3461a9d3787412d30e8e7eb907c79180c4a57bf7c04ef" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "semver" version = "0.11.0" @@ -4207,6 +4196,7 @@ dependencies = [ "bincode", "blake3", "bls12_381 0.8.0", + "bytemuck", "cfg-if", "curve25519-dalek", "elf", @@ -4396,6 +4386,7 @@ dependencies = [ "p3-merkle-tree", "p3-poseidon2", "p3-symmetric", + "p3-util", "serde", "serde_with", "sphinx-core", @@ -4419,8 +4410,11 @@ dependencies = [ name = "sphinx-recursion-gnark-ffi" version = "1.0.0" dependencies = [ + "anyhow", + "bincode", "bindgen", "cfg-if", + "hex", "log", "num-bigint 0.4.5", "p3-baby-bear", @@ -4429,6 +4423,7 @@ dependencies = [ "rand", "serde", "serde_json", + "sha2", "sphinx-core", "sphinx-recursion-compiler", "tempfile", @@ -4491,6 +4486,7 @@ dependencies = [ "strum", "strum_macros", "tempfile", + "thiserror", "tokio", "tracing", "twirp", @@ -4777,12 +4773,13 @@ dependencies = [ ] [[package]] -name = "tokio-native-tls" -version = "0.3.1" +name = "tokio-rustls" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "native-tls", + "rustls", + "rustls-pki-types", "tokio", ] @@ -5055,6 +5052,12 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" version = "2.5.0" @@ -5246,6 +5249,15 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki-roots" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "which" version = "4.4.2" diff --git a/examples/bls12381-pairing/script/Cargo.lock b/examples/bls12381-pairing/script/Cargo.lock index 3363a72ce..27760e2c4 100644 --- a/examples/bls12381-pairing/script/Cargo.lock +++ b/examples/bls12381-pairing/script/Cargo.lock @@ -621,16 +621,16 @@ dependencies = [ [[package]] name = "blake3" -version = "1.5.1" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30cca6d3674597c30ddf2c587bf8d9d65c9a84d2326d941cc79c9842dfe0ef52" +checksum = "e9ec96fe9a81b5e365f9db71fe00edc4fe4ca2cc7dcb7861f0603012a7caa210" dependencies = [ "arrayref", "arrayvec", "cc", "cfg-if", "constant_time_eq", - "rayon", + "rayon-core", ] [[package]] @@ -699,6 +699,12 @@ version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" +[[package]] +name = "bytemuck" +version = "1.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e" + [[package]] name = "byteorder" version = "1.5.0" @@ -1622,21 +1628,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "form_urlencoded" version = "1.2.1" @@ -2090,19 +2081,21 @@ dependencies = [ ] [[package]] -name = "hyper-tls" -version = "0.6.0" +name = "hyper-rustls" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" dependencies = [ - "bytes", - "http-body-util", + "futures-util", + "http 1.1.0", "hyper 1.3.1", "hyper-util", - "native-tls", + "rustls", + "rustls-pki-types", "tokio", - "tokio-native-tls", + "tokio-rustls", "tower-service", + "webpki-roots", ] [[package]] @@ -2323,7 +2316,7 @@ checksum = "6971da4d9c3aa03c3d8f3ff0f4155b534aad021292003895a469716b2a230378" dependencies = [ "base64 0.21.7", "pem", - "ring", + "ring 0.16.20", "serde", "serde_json", "simple_asn1", @@ -2518,23 +2511,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "native-tls" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" -dependencies = [ - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - [[package]] name = "nohash-hasher" version = "0.2.0" @@ -2759,50 +2735,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "openssl" -version = "0.10.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" -dependencies = [ - "bitflags 2.5.0", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", -] - -[[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "openssl-sys" -version = "0.9.102" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "overload" version = "0.1.1" @@ -3404,6 +3336,53 @@ version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" +[[package]] +name = "quinn" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4ceeeeabace7857413798eb1ffa1e9c905a9946a57d81fb69b4b71c4d8eb3ad" +dependencies = [ + "bytes", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "quinn-proto" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddf517c03a109db8100448a4be38d498df8a210a99fe0e1b9eaf39e78c640efe" +dependencies = [ + "bytes", + "rand", + "ring 0.17.8", + "rustc-hash", + "rustls", + "slab", + "thiserror", + "tinyvec", + "tracing", +] + +[[package]] +name = "quinn-udp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9096629c45860fc7fb143e125eb826b5e721e10be3263160c7d60ca832cf8c46" +dependencies = [ + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.52.0", +] + [[package]] name = "quote" version = "1.0.36" @@ -3590,23 +3569,25 @@ dependencies = [ "http-body 1.0.0", "http-body-util", "hyper 1.3.1", - "hyper-tls", + "hyper-rustls", "hyper-util", "ipnet", "js-sys", "log", "mime", - "native-tls", "once_cell", "percent-encoding", "pin-project-lite", + "quinn", + "rustls", "rustls-pemfile", + "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper 1.0.1", "tokio", - "tokio-native-tls", + "tokio-rustls", "tokio-util", "tower-service", "url", @@ -3614,6 +3595,7 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", + "webpki-roots", "winreg 0.52.0", ] @@ -3652,11 +3634,26 @@ dependencies = [ "libc", "once_cell", "spin 0.5.2", - "untrusted", + "untrusted 0.7.1", "web-sys", "winapi", ] +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin 0.9.8", + "untrusted 0.9.0", + "windows-sys 0.52.0", +] + [[package]] name = "ripemd" version = "0.1.3" @@ -3777,6 +3774,20 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rustls" +version = "0.23.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" +dependencies = [ + "once_cell", + "ring 0.17.8", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + [[package]] name = "rustls-pemfile" version = "2.1.2" @@ -3793,6 +3804,17 @@ version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" +[[package]] +name = "rustls-webpki" +version = "0.102.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e" +dependencies = [ + "ring 0.17.8", + "rustls-pki-types", + "untrusted 0.9.0", +] + [[package]] name = "rustversion" version = "1.0.17" @@ -3868,15 +3890,6 @@ dependencies = [ "sdd", ] -[[package]] -name = "schannel" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" -dependencies = [ - "windows-sys 0.52.0", -] - [[package]] name = "scopeguard" version = "1.2.0" @@ -3915,29 +3928,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "security-framework" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" -dependencies = [ - "bitflags 2.5.0", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "semver" version = "0.11.0" @@ -4211,6 +4201,7 @@ dependencies = [ "bincode", "blake3", "bls12_381 0.8.0", + "bytemuck", "cfg-if", "curve25519-dalek", "elf", @@ -4400,6 +4391,7 @@ dependencies = [ "p3-merkle-tree", "p3-poseidon2", "p3-symmetric", + "p3-util", "serde", "serde_with", "sphinx-core", @@ -4423,8 +4415,11 @@ dependencies = [ name = "sphinx-recursion-gnark-ffi" version = "1.0.0" dependencies = [ + "anyhow", + "bincode", "bindgen", "cfg-if", + "hex", "log", "num-bigint 0.4.5", "p3-baby-bear", @@ -4433,6 +4428,7 @@ dependencies = [ "rand", "serde", "serde_json", + "sha2", "sphinx-core", "sphinx-recursion-compiler", "tempfile", @@ -4495,6 +4491,7 @@ dependencies = [ "strum", "strum_macros", "tempfile", + "thiserror", "tokio", "tracing", "twirp", @@ -4775,12 +4772,13 @@ dependencies = [ ] [[package]] -name = "tokio-native-tls" -version = "0.3.1" +name = "tokio-rustls" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "native-tls", + "rustls", + "rustls-pki-types", "tokio", ] @@ -5063,6 +5061,12 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" version = "2.5.0" @@ -5254,6 +5258,15 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki-roots" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "which" version = "4.4.2" diff --git a/examples/bls12381-pairing/script/src/main.rs b/examples/bls12381-pairing/script/src/main.rs index e4318771e..b8d7cc219 100644 --- a/examples/bls12381-pairing/script/src/main.rs +++ b/examples/bls12381-pairing/script/src/main.rs @@ -1,4 +1,4 @@ -use sphinx_sdk::{utils, ProverClient, SphinxStdin}; +use sphinx_sdk::{utils, ProverClient, SphinxProof, SphinxStdin}; /// The ELF we want to execute inside the zkVM. const ELF: &[u8] = include_bytes!("../../program/elf/riscv32im-succinct-zkvm-elf"); @@ -18,10 +18,16 @@ fn main() { // Verify proof. client.verify(&proof, &vk).expect("verification failed"); - // Save the proof. + // Test a round trip of proof serialization and deserialization. proof - .save("proof-with-pis.json") + .save("proof-with-io.bin") .expect("saving proof failed"); + let deserialized_proof = SphinxProof::load("proof-with-io.bin").expect("loading proof failed"); + + // Verify the deserialized proof. + client + .verify(&deserialized_proof, &vk) + .expect("verification failed"); println!("successfully generated and verified proof for the program!") } diff --git a/examples/chess/program/Cargo.lock b/examples/chess/program/Cargo.lock index e14655472..02216b225 100644 --- a/examples/chess/program/Cargo.lock +++ b/examples/chess/program/Cargo.lock @@ -334,6 +334,12 @@ dependencies = [ "signature", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.154" @@ -594,6 +600,7 @@ dependencies = [ "cfg-if", "getrandom", "k256", + "lazy_static", "once_cell", "rand 0.8.5", "sha2", diff --git a/examples/chess/program/elf/riscv32im-succinct-zkvm-elf b/examples/chess/program/elf/riscv32im-succinct-zkvm-elf index 913091304..4a3710a4e 100755 Binary files a/examples/chess/program/elf/riscv32im-succinct-zkvm-elf and b/examples/chess/program/elf/riscv32im-succinct-zkvm-elf differ diff --git a/examples/chess/script/Cargo.lock b/examples/chess/script/Cargo.lock index 920840f0f..0f575e6cb 100644 --- a/examples/chess/script/Cargo.lock +++ b/examples/chess/script/Cargo.lock @@ -621,16 +621,16 @@ dependencies = [ [[package]] name = "blake3" -version = "1.5.1" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30cca6d3674597c30ddf2c587bf8d9d65c9a84d2326d941cc79c9842dfe0ef52" +checksum = "e9ec96fe9a81b5e365f9db71fe00edc4fe4ca2cc7dcb7861f0603012a7caa210" dependencies = [ "arrayref", "arrayvec", "cc", "cfg-if", "constant_time_eq", - "rayon", + "rayon-core", ] [[package]] @@ -690,6 +690,12 @@ version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" +[[package]] +name = "bytemuck" +version = "1.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e" + [[package]] name = "byteorder" version = "1.5.0" @@ -1621,21 +1627,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "form_urlencoded" version = "1.2.1" @@ -2089,19 +2080,21 @@ dependencies = [ ] [[package]] -name = "hyper-tls" -version = "0.6.0" +name = "hyper-rustls" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" dependencies = [ - "bytes", - "http-body-util", + "futures-util", + "http 1.1.0", "hyper 1.3.1", "hyper-util", - "native-tls", + "rustls", + "rustls-pki-types", "tokio", - "tokio-native-tls", + "tokio-rustls", "tower-service", + "webpki-roots", ] [[package]] @@ -2322,7 +2315,7 @@ checksum = "6971da4d9c3aa03c3d8f3ff0f4155b534aad021292003895a469716b2a230378" dependencies = [ "base64 0.21.7", "pem", - "ring", + "ring 0.16.20", "serde", "serde_json", "simple_asn1", @@ -2517,24 +2510,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "native-tls" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" -dependencies = [ - "lazy_static", - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - [[package]] name = "nohash-hasher" version = "0.2.0" @@ -2759,50 +2734,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "openssl" -version = "0.10.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" -dependencies = [ - "bitflags 2.5.0", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.63", -] - -[[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "openssl-sys" -version = "0.9.102" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "overload" version = "0.1.1" @@ -3404,6 +3335,53 @@ version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" +[[package]] +name = "quinn" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4ceeeeabace7857413798eb1ffa1e9c905a9946a57d81fb69b4b71c4d8eb3ad" +dependencies = [ + "bytes", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "quinn-proto" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddf517c03a109db8100448a4be38d498df8a210a99fe0e1b9eaf39e78c640efe" +dependencies = [ + "bytes", + "rand", + "ring 0.17.8", + "rustc-hash", + "rustls", + "slab", + "thiserror", + "tinyvec", + "tracing", +] + +[[package]] +name = "quinn-udp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9096629c45860fc7fb143e125eb826b5e721e10be3263160c7d60ca832cf8c46" +dependencies = [ + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.52.0", +] + [[package]] name = "quote" version = "1.0.36" @@ -3590,23 +3568,25 @@ dependencies = [ "http-body 1.0.0", "http-body-util", "hyper 1.3.1", - "hyper-tls", + "hyper-rustls", "hyper-util", "ipnet", "js-sys", "log", "mime", - "native-tls", "once_cell", "percent-encoding", "pin-project-lite", + "quinn", + "rustls", "rustls-pemfile", + "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper 1.0.1", "tokio", - "tokio-native-tls", + "tokio-rustls", "tokio-util", "tower-service", "url", @@ -3614,6 +3594,7 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", + "webpki-roots", "winreg 0.52.0", ] @@ -3652,11 +3633,26 @@ dependencies = [ "libc", "once_cell", "spin 0.5.2", - "untrusted", + "untrusted 0.7.1", "web-sys", "winapi", ] +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin 0.9.8", + "untrusted 0.9.0", + "windows-sys 0.52.0", +] + [[package]] name = "ripemd" version = "0.1.3" @@ -3777,6 +3773,20 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rustls" +version = "0.23.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" +dependencies = [ + "once_cell", + "ring 0.17.8", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + [[package]] name = "rustls-pemfile" version = "2.1.2" @@ -3793,6 +3803,17 @@ version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" +[[package]] +name = "rustls-webpki" +version = "0.102.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e" +dependencies = [ + "ring 0.17.8", + "rustls-pki-types", + "untrusted 0.9.0", +] + [[package]] name = "rustversion" version = "1.0.17" @@ -3868,15 +3889,6 @@ dependencies = [ "sdd", ] -[[package]] -name = "schannel" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" -dependencies = [ - "windows-sys 0.52.0", -] - [[package]] name = "scopeguard" version = "1.2.0" @@ -3915,29 +3927,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "security-framework" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" -dependencies = [ - "bitflags 2.5.0", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "semver" version = "0.11.0" @@ -4211,6 +4200,7 @@ dependencies = [ "bincode", "blake3", "bls12_381 0.8.0", + "bytemuck", "cfg-if", "curve25519-dalek", "elf", @@ -4400,6 +4390,7 @@ dependencies = [ "p3-merkle-tree", "p3-poseidon2", "p3-symmetric", + "p3-util", "serde", "serde_with", "sphinx-core", @@ -4423,8 +4414,11 @@ dependencies = [ name = "sphinx-recursion-gnark-ffi" version = "1.0.0" dependencies = [ + "anyhow", + "bincode", "bindgen", "cfg-if", + "hex", "log", "num-bigint 0.4.5", "p3-baby-bear", @@ -4433,6 +4427,7 @@ dependencies = [ "rand", "serde", "serde_json", + "sha2", "sphinx-core", "sphinx-recursion-compiler", "tempfile", @@ -4495,6 +4490,7 @@ dependencies = [ "strum", "strum_macros", "tempfile", + "thiserror", "tokio", "tracing", "twirp", @@ -4775,12 +4771,13 @@ dependencies = [ ] [[package]] -name = "tokio-native-tls" -version = "0.3.1" +name = "tokio-rustls" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "native-tls", + "rustls", + "rustls-pki-types", "tokio", ] @@ -5063,6 +5060,12 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" version = "2.5.0" @@ -5254,6 +5257,15 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki-roots" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "which" version = "4.4.2" diff --git a/examples/chess/script/src/main.rs b/examples/chess/script/src/main.rs index 07f2e502f..21c30b7fe 100644 --- a/examples/chess/script/src/main.rs +++ b/examples/chess/script/src/main.rs @@ -1,4 +1,4 @@ -use sphinx_sdk::{ProverClient, SphinxStdin}; +use sphinx_sdk::{ProverClient, SphinxProof, SphinxStdin}; const ELF: &[u8] = include_bytes!("../../program/elf/riscv32im-succinct-zkvm-elf"); @@ -24,10 +24,16 @@ fn main() { // Verify proof. client.verify(&proof, &vk).expect("verification failed"); - // Save proof. + // Test a round trip of proof serialization and deserialization. proof - .save("proof-with-io.json") + .save("proof-with-io.bin") .expect("saving proof failed"); + let deserialized_proof = SphinxProof::load("proof-with-io.bin").expect("loading proof failed"); + + // Verify the deserialized proof. + client + .verify(&deserialized_proof, &vk) + .expect("verification failed"); println!("successfully generated and verified proof for the program!") } diff --git a/examples/cycle-tracking/program/Cargo.lock b/examples/cycle-tracking/program/Cargo.lock index b36154c8d..882764860 100644 --- a/examples/cycle-tracking/program/Cargo.lock +++ b/examples/cycle-tracking/program/Cargo.lock @@ -252,6 +252,12 @@ dependencies = [ "signature", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.154" @@ -439,6 +445,7 @@ dependencies = [ "cfg-if", "getrandom", "k256", + "lazy_static", "once_cell", "rand", "sha2", diff --git a/examples/cycle-tracking/program/elf/riscv32im-succinct-zkvm-elf b/examples/cycle-tracking/program/elf/riscv32im-succinct-zkvm-elf index 22f816a19..3ffe8a6e1 100755 Binary files a/examples/cycle-tracking/program/elf/riscv32im-succinct-zkvm-elf and b/examples/cycle-tracking/program/elf/riscv32im-succinct-zkvm-elf differ diff --git a/examples/cycle-tracking/script/Cargo.lock b/examples/cycle-tracking/script/Cargo.lock index a4887bcfb..1bd4aeae6 100644 --- a/examples/cycle-tracking/script/Cargo.lock +++ b/examples/cycle-tracking/script/Cargo.lock @@ -621,16 +621,16 @@ dependencies = [ [[package]] name = "blake3" -version = "1.5.1" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30cca6d3674597c30ddf2c587bf8d9d65c9a84d2326d941cc79c9842dfe0ef52" +checksum = "e9ec96fe9a81b5e365f9db71fe00edc4fe4ca2cc7dcb7861f0603012a7caa210" dependencies = [ "arrayref", "arrayvec", "cc", "cfg-if", "constant_time_eq", - "rayon", + "rayon-core", ] [[package]] @@ -690,6 +690,12 @@ version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" +[[package]] +name = "bytemuck" +version = "1.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e" + [[package]] name = "byteorder" version = "1.5.0" @@ -1621,21 +1627,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "form_urlencoded" version = "1.2.1" @@ -2089,19 +2080,21 @@ dependencies = [ ] [[package]] -name = "hyper-tls" -version = "0.6.0" +name = "hyper-rustls" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" dependencies = [ - "bytes", - "http-body-util", + "futures-util", + "http 1.1.0", "hyper 1.3.1", "hyper-util", - "native-tls", + "rustls", + "rustls-pki-types", "tokio", - "tokio-native-tls", + "tokio-rustls", "tower-service", + "webpki-roots", ] [[package]] @@ -2322,7 +2315,7 @@ checksum = "6971da4d9c3aa03c3d8f3ff0f4155b534aad021292003895a469716b2a230378" dependencies = [ "base64 0.21.7", "pem", - "ring", + "ring 0.16.20", "serde", "serde_json", "simple_asn1", @@ -2517,24 +2510,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "native-tls" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" -dependencies = [ - "lazy_static", - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - [[package]] name = "nohash-hasher" version = "0.2.0" @@ -2759,50 +2734,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "openssl" -version = "0.10.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" -dependencies = [ - "bitflags 2.5.0", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.63", -] - -[[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "openssl-sys" -version = "0.9.102" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "overload" version = "0.1.1" @@ -3404,6 +3335,53 @@ version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" +[[package]] +name = "quinn" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4ceeeeabace7857413798eb1ffa1e9c905a9946a57d81fb69b4b71c4d8eb3ad" +dependencies = [ + "bytes", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "quinn-proto" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddf517c03a109db8100448a4be38d498df8a210a99fe0e1b9eaf39e78c640efe" +dependencies = [ + "bytes", + "rand", + "ring 0.17.8", + "rustc-hash", + "rustls", + "slab", + "thiserror", + "tinyvec", + "tracing", +] + +[[package]] +name = "quinn-udp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9096629c45860fc7fb143e125eb826b5e721e10be3263160c7d60ca832cf8c46" +dependencies = [ + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.52.0", +] + [[package]] name = "quote" version = "1.0.36" @@ -3590,23 +3568,25 @@ dependencies = [ "http-body 1.0.0", "http-body-util", "hyper 1.3.1", - "hyper-tls", + "hyper-rustls", "hyper-util", "ipnet", "js-sys", "log", "mime", - "native-tls", "once_cell", "percent-encoding", "pin-project-lite", + "quinn", + "rustls", "rustls-pemfile", + "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper 1.0.1", "tokio", - "tokio-native-tls", + "tokio-rustls", "tokio-util", "tower-service", "url", @@ -3614,6 +3594,7 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", + "webpki-roots", "winreg 0.52.0", ] @@ -3652,11 +3633,26 @@ dependencies = [ "libc", "once_cell", "spin 0.5.2", - "untrusted", + "untrusted 0.7.1", "web-sys", "winapi", ] +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin 0.9.8", + "untrusted 0.9.0", + "windows-sys 0.52.0", +] + [[package]] name = "ripemd" version = "0.1.3" @@ -3777,6 +3773,20 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rustls" +version = "0.23.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" +dependencies = [ + "once_cell", + "ring 0.17.8", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + [[package]] name = "rustls-pemfile" version = "2.1.2" @@ -3793,6 +3803,17 @@ version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" +[[package]] +name = "rustls-webpki" +version = "0.102.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e" +dependencies = [ + "ring 0.17.8", + "rustls-pki-types", + "untrusted 0.9.0", +] + [[package]] name = "rustversion" version = "1.0.17" @@ -3868,15 +3889,6 @@ dependencies = [ "sdd", ] -[[package]] -name = "schannel" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" -dependencies = [ - "windows-sys 0.52.0", -] - [[package]] name = "scopeguard" version = "1.2.0" @@ -3915,29 +3927,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "security-framework" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" -dependencies = [ - "bitflags 2.5.0", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "semver" version = "0.11.0" @@ -4211,6 +4200,7 @@ dependencies = [ "bincode", "blake3", "bls12_381 0.8.0", + "bytemuck", "cfg-if", "curve25519-dalek", "elf", @@ -4400,6 +4390,7 @@ dependencies = [ "p3-merkle-tree", "p3-poseidon2", "p3-symmetric", + "p3-util", "serde", "serde_with", "sphinx-core", @@ -4423,8 +4414,11 @@ dependencies = [ name = "sphinx-recursion-gnark-ffi" version = "1.0.0" dependencies = [ + "anyhow", + "bincode", "bindgen", "cfg-if", + "hex", "log", "num-bigint 0.4.5", "p3-baby-bear", @@ -4433,6 +4427,7 @@ dependencies = [ "rand", "serde", "serde_json", + "sha2", "sphinx-core", "sphinx-recursion-compiler", "tempfile", @@ -4495,6 +4490,7 @@ dependencies = [ "strum", "strum_macros", "tempfile", + "thiserror", "tokio", "tracing", "twirp", @@ -4775,12 +4771,13 @@ dependencies = [ ] [[package]] -name = "tokio-native-tls" -version = "0.3.1" +name = "tokio-rustls" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "native-tls", + "rustls", + "rustls-pki-types", "tokio", ] @@ -5063,6 +5060,12 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" version = "2.5.0" @@ -5254,6 +5257,15 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki-roots" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "which" version = "4.4.2" diff --git a/examples/cycle-tracking/script/src/main.rs b/examples/cycle-tracking/script/src/main.rs index e4318771e..f94c3ec92 100644 --- a/examples/cycle-tracking/script/src/main.rs +++ b/examples/cycle-tracking/script/src/main.rs @@ -1,4 +1,4 @@ -use sphinx_sdk::{utils, ProverClient, SphinxStdin}; +use sphinx_sdk::{utils, ProverClient, SphinxProof, SphinxStdin}; /// The ELF we want to execute inside the zkVM. const ELF: &[u8] = include_bytes!("../../program/elf/riscv32im-succinct-zkvm-elf"); @@ -18,10 +18,16 @@ fn main() { // Verify proof. client.verify(&proof, &vk).expect("verification failed"); - // Save the proof. + // Test a round trip of proof serialization and deserialization. proof - .save("proof-with-pis.json") + .save("proof-with-pis.bin") .expect("saving proof failed"); + let deserialized_proof = SphinxProof::load("proof-with-pis.bin").expect("loading proof failed"); + + // Verify the deserialized proof. + client + .verify(&deserialized_proof, &vk) + .expect("verification failed"); println!("successfully generated and verified proof for the program!") } diff --git a/examples/fibonacci/program/Cargo.lock b/examples/fibonacci/program/Cargo.lock index 3e42b0846..fccd6b9de 100644 --- a/examples/fibonacci/program/Cargo.lock +++ b/examples/fibonacci/program/Cargo.lock @@ -251,6 +251,12 @@ dependencies = [ "signature", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.154" @@ -429,6 +435,7 @@ dependencies = [ "cfg-if", "getrandom", "k256", + "lazy_static", "once_cell", "rand", "sha2", diff --git a/examples/fibonacci/program/elf/riscv32im-succinct-zkvm-elf b/examples/fibonacci/program/elf/riscv32im-succinct-zkvm-elf index 83938c44d..b3087ebd8 100755 Binary files a/examples/fibonacci/program/elf/riscv32im-succinct-zkvm-elf and b/examples/fibonacci/program/elf/riscv32im-succinct-zkvm-elf differ diff --git a/examples/fibonacci/script/Cargo.lock b/examples/fibonacci/script/Cargo.lock index c1ae44812..609745b86 100644 --- a/examples/fibonacci/script/Cargo.lock +++ b/examples/fibonacci/script/Cargo.lock @@ -621,16 +621,16 @@ dependencies = [ [[package]] name = "blake3" -version = "1.5.1" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30cca6d3674597c30ddf2c587bf8d9d65c9a84d2326d941cc79c9842dfe0ef52" +checksum = "e9ec96fe9a81b5e365f9db71fe00edc4fe4ca2cc7dcb7861f0603012a7caa210" dependencies = [ "arrayref", "arrayvec", "cc", "cfg-if", "constant_time_eq", - "rayon", + "rayon-core", ] [[package]] @@ -690,6 +690,12 @@ version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" +[[package]] +name = "bytemuck" +version = "1.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e" + [[package]] name = "byteorder" version = "1.5.0" @@ -1622,21 +1628,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "form_urlencoded" version = "1.2.1" @@ -2090,19 +2081,21 @@ dependencies = [ ] [[package]] -name = "hyper-tls" -version = "0.6.0" +name = "hyper-rustls" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" dependencies = [ - "bytes", - "http-body-util", + "futures-util", + "http 1.1.0", "hyper 1.3.1", "hyper-util", - "native-tls", + "rustls", + "rustls-pki-types", "tokio", - "tokio-native-tls", + "tokio-rustls", "tower-service", + "webpki-roots", ] [[package]] @@ -2323,7 +2316,7 @@ checksum = "6971da4d9c3aa03c3d8f3ff0f4155b534aad021292003895a469716b2a230378" dependencies = [ "base64 0.21.7", "pem", - "ring", + "ring 0.16.20", "serde", "serde_json", "simple_asn1", @@ -2518,24 +2511,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "native-tls" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" -dependencies = [ - "lazy_static", - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - [[package]] name = "nohash-hasher" version = "0.2.0" @@ -2760,50 +2735,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "openssl" -version = "0.10.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" -dependencies = [ - "bitflags 2.5.0", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.63", -] - -[[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "openssl-sys" -version = "0.9.102" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "overload" version = "0.1.1" @@ -3405,6 +3336,53 @@ version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" +[[package]] +name = "quinn" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4ceeeeabace7857413798eb1ffa1e9c905a9946a57d81fb69b4b71c4d8eb3ad" +dependencies = [ + "bytes", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "quinn-proto" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddf517c03a109db8100448a4be38d498df8a210a99fe0e1b9eaf39e78c640efe" +dependencies = [ + "bytes", + "rand", + "ring 0.17.8", + "rustc-hash", + "rustls", + "slab", + "thiserror", + "tinyvec", + "tracing", +] + +[[package]] +name = "quinn-udp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9096629c45860fc7fb143e125eb826b5e721e10be3263160c7d60ca832cf8c46" +dependencies = [ + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.52.0", +] + [[package]] name = "quote" version = "1.0.36" @@ -3591,23 +3569,25 @@ dependencies = [ "http-body 1.0.0", "http-body-util", "hyper 1.3.1", - "hyper-tls", + "hyper-rustls", "hyper-util", "ipnet", "js-sys", "log", "mime", - "native-tls", "once_cell", "percent-encoding", "pin-project-lite", + "quinn", + "rustls", "rustls-pemfile", + "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper 1.0.1", "tokio", - "tokio-native-tls", + "tokio-rustls", "tokio-util", "tower-service", "url", @@ -3615,6 +3595,7 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", + "webpki-roots", "winreg 0.52.0", ] @@ -3653,11 +3634,26 @@ dependencies = [ "libc", "once_cell", "spin 0.5.2", - "untrusted", + "untrusted 0.7.1", "web-sys", "winapi", ] +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin 0.9.8", + "untrusted 0.9.0", + "windows-sys 0.52.0", +] + [[package]] name = "ripemd" version = "0.1.3" @@ -3778,6 +3774,20 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rustls" +version = "0.23.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" +dependencies = [ + "once_cell", + "ring 0.17.8", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + [[package]] name = "rustls-pemfile" version = "2.1.2" @@ -3794,6 +3804,17 @@ version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" +[[package]] +name = "rustls-webpki" +version = "0.102.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e" +dependencies = [ + "ring 0.17.8", + "rustls-pki-types", + "untrusted 0.9.0", +] + [[package]] name = "rustversion" version = "1.0.17" @@ -3869,15 +3890,6 @@ dependencies = [ "sdd", ] -[[package]] -name = "schannel" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" -dependencies = [ - "windows-sys 0.52.0", -] - [[package]] name = "scopeguard" version = "1.2.0" @@ -3916,29 +3928,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "security-framework" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" -dependencies = [ - "bitflags 2.5.0", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "semver" version = "0.11.0" @@ -4212,6 +4201,7 @@ dependencies = [ "bincode", "blake3", "bls12_381 0.8.0", + "bytemuck", "cfg-if", "curve25519-dalek", "elf", @@ -4401,6 +4391,7 @@ dependencies = [ "p3-merkle-tree", "p3-poseidon2", "p3-symmetric", + "p3-util", "serde", "serde_with", "sphinx-core", @@ -4424,8 +4415,11 @@ dependencies = [ name = "sphinx-recursion-gnark-ffi" version = "1.0.0" dependencies = [ + "anyhow", + "bincode", "bindgen", "cfg-if", + "hex", "log", "num-bigint 0.4.5", "p3-baby-bear", @@ -4434,6 +4428,7 @@ dependencies = [ "rand", "serde", "serde_json", + "sha2", "sphinx-core", "sphinx-recursion-compiler", "tempfile", @@ -4496,6 +4491,7 @@ dependencies = [ "strum", "strum_macros", "tempfile", + "thiserror", "tokio", "tracing", "twirp", @@ -4776,12 +4772,13 @@ dependencies = [ ] [[package]] -name = "tokio-native-tls" -version = "0.3.1" +name = "tokio-rustls" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "native-tls", + "rustls", + "rustls-pki-types", "tokio", ] @@ -5064,6 +5061,12 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" version = "2.5.0" @@ -5255,6 +5258,15 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki-roots" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "which" version = "4.4.2" diff --git a/examples/fibonacci/script/bin/compressed.rs b/examples/fibonacci/script/bin/compressed.rs index 1706b9d64..d21bdd49f 100644 --- a/examples/fibonacci/script/bin/compressed.rs +++ b/examples/fibonacci/script/bin/compressed.rs @@ -30,7 +30,7 @@ fn main() { // Save the proof. proof - .save("compressed-proof-with-pis.json") + .save("compressed-proof-with-pis.bin") .expect("saving proof failed"); println!("successfully generated and verified proof for the program!") diff --git a/examples/fibonacci/script/bin/plonk_bn254.rs b/examples/fibonacci/script/bin/plonk_bn254.rs index 71641d708..435773aca 100644 --- a/examples/fibonacci/script/bin/plonk_bn254.rs +++ b/examples/fibonacci/script/bin/plonk_bn254.rs @@ -34,7 +34,7 @@ fn main() { // Save the proof. proof - .save("proof-with-pis.json") + .save("proof-with-pis.bin") .expect("saving proof failed"); println!("successfully generated and verified proof for the program!") diff --git a/examples/fibonacci/script/src/main.rs b/examples/fibonacci/script/src/main.rs index c9b9b9492..316379989 100644 --- a/examples/fibonacci/script/src/main.rs +++ b/examples/fibonacci/script/src/main.rs @@ -1,4 +1,4 @@ -use sphinx_sdk::{utils, ProverClient, SphinxStdin}; +use sphinx_sdk::{utils, ProverClient, SphinxProof, SphinxStdin}; /// The ELF we want to execute inside the zkVM. const ELF: &[u8] = include_bytes!("../../program/elf/riscv32im-succinct-zkvm-elf"); @@ -16,7 +16,7 @@ fn main() { // Generate the proof for the given program and input. let client = ProverClient::new(); let (pk, vk) = client.setup(ELF); - let mut proof = client.prove_compressed(&pk, stdin).unwrap(); + let mut proof = client.prove(&pk, stdin).unwrap(); println!("generated proof"); @@ -29,14 +29,18 @@ fn main() { println!("b: {}", b); // Verify proof and public values - client - .verify_compressed(&proof, &vk) - .expect("verification failed"); + client.verify(&proof, &vk).expect("verification failed"); - // Save the proof. + // Test a round trip of proof serialization and deserialization. proof - .save("proof-with-pis.json") + .save("proof-with-pis.bin") .expect("saving proof failed"); + let deserialized_proof = SphinxProof::load("proof-with-pis.bin").expect("loading proof failed"); + + // Verify the deserialized proof. + client + .verify(&deserialized_proof, &vk) + .expect("verification failed"); println!("successfully generated and verified proof for the program!") } diff --git a/examples/io/program/Cargo.lock b/examples/io/program/Cargo.lock index 4cea90ccb..2f91c3297 100644 --- a/examples/io/program/Cargo.lock +++ b/examples/io/program/Cargo.lock @@ -252,6 +252,12 @@ dependencies = [ "signature", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.154" @@ -430,6 +436,7 @@ dependencies = [ "cfg-if", "getrandom", "k256", + "lazy_static", "once_cell", "rand", "sha2", diff --git a/examples/io/program/elf/riscv32im-succinct-zkvm-elf b/examples/io/program/elf/riscv32im-succinct-zkvm-elf index e961fd9d4..fbba4ba98 100755 Binary files a/examples/io/program/elf/riscv32im-succinct-zkvm-elf and b/examples/io/program/elf/riscv32im-succinct-zkvm-elf differ diff --git a/examples/io/script/Cargo.lock b/examples/io/script/Cargo.lock index c3a4ed456..dcd78ab1c 100644 --- a/examples/io/script/Cargo.lock +++ b/examples/io/script/Cargo.lock @@ -621,16 +621,16 @@ dependencies = [ [[package]] name = "blake3" -version = "1.5.1" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30cca6d3674597c30ddf2c587bf8d9d65c9a84d2326d941cc79c9842dfe0ef52" +checksum = "e9ec96fe9a81b5e365f9db71fe00edc4fe4ca2cc7dcb7861f0603012a7caa210" dependencies = [ "arrayref", "arrayvec", "cc", "cfg-if", "constant_time_eq", - "rayon", + "rayon-core", ] [[package]] @@ -690,6 +690,12 @@ version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" +[[package]] +name = "bytemuck" +version = "1.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e" + [[package]] name = "byteorder" version = "1.5.0" @@ -1613,21 +1619,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "form_urlencoded" version = "1.2.1" @@ -2081,19 +2072,21 @@ dependencies = [ ] [[package]] -name = "hyper-tls" -version = "0.6.0" +name = "hyper-rustls" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" dependencies = [ - "bytes", - "http-body-util", + "futures-util", + "http 1.1.0", "hyper 1.3.1", "hyper-util", - "native-tls", + "rustls", + "rustls-pki-types", "tokio", - "tokio-native-tls", + "tokio-rustls", "tower-service", + "webpki-roots", ] [[package]] @@ -2323,7 +2316,7 @@ checksum = "6971da4d9c3aa03c3d8f3ff0f4155b534aad021292003895a469716b2a230378" dependencies = [ "base64 0.21.7", "pem", - "ring", + "ring 0.16.20", "serde", "serde_json", "simple_asn1", @@ -2518,24 +2511,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "native-tls" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" -dependencies = [ - "lazy_static", - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - [[package]] name = "nohash-hasher" version = "0.2.0" @@ -2760,50 +2735,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "openssl" -version = "0.10.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" -dependencies = [ - "bitflags 2.5.0", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.63", -] - -[[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "openssl-sys" -version = "0.9.102" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "overload" version = "0.1.1" @@ -3405,6 +3336,53 @@ version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" +[[package]] +name = "quinn" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4ceeeeabace7857413798eb1ffa1e9c905a9946a57d81fb69b4b71c4d8eb3ad" +dependencies = [ + "bytes", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "quinn-proto" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddf517c03a109db8100448a4be38d498df8a210a99fe0e1b9eaf39e78c640efe" +dependencies = [ + "bytes", + "rand", + "ring 0.17.8", + "rustc-hash", + "rustls", + "slab", + "thiserror", + "tinyvec", + "tracing", +] + +[[package]] +name = "quinn-udp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9096629c45860fc7fb143e125eb826b5e721e10be3263160c7d60ca832cf8c46" +dependencies = [ + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.52.0", +] + [[package]] name = "quote" version = "1.0.36" @@ -3591,23 +3569,25 @@ dependencies = [ "http-body 1.0.0", "http-body-util", "hyper 1.3.1", - "hyper-tls", + "hyper-rustls", "hyper-util", "ipnet", "js-sys", "log", "mime", - "native-tls", "once_cell", "percent-encoding", "pin-project-lite", + "quinn", + "rustls", "rustls-pemfile", + "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper 1.0.1", "tokio", - "tokio-native-tls", + "tokio-rustls", "tokio-util", "tower-service", "url", @@ -3615,6 +3595,7 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", + "webpki-roots", "winreg 0.52.0", ] @@ -3653,11 +3634,26 @@ dependencies = [ "libc", "once_cell", "spin 0.5.2", - "untrusted", + "untrusted 0.7.1", "web-sys", "winapi", ] +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin 0.9.8", + "untrusted 0.9.0", + "windows-sys 0.52.0", +] + [[package]] name = "ripemd" version = "0.1.3" @@ -3778,6 +3774,20 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rustls" +version = "0.23.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" +dependencies = [ + "once_cell", + "ring 0.17.8", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + [[package]] name = "rustls-pemfile" version = "2.1.2" @@ -3794,6 +3804,17 @@ version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" +[[package]] +name = "rustls-webpki" +version = "0.102.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e" +dependencies = [ + "ring 0.17.8", + "rustls-pki-types", + "untrusted 0.9.0", +] + [[package]] name = "rustversion" version = "1.0.17" @@ -3869,15 +3890,6 @@ dependencies = [ "sdd", ] -[[package]] -name = "schannel" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" -dependencies = [ - "windows-sys 0.52.0", -] - [[package]] name = "scopeguard" version = "1.2.0" @@ -3916,29 +3928,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "security-framework" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" -dependencies = [ - "bitflags 2.5.0", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "semver" version = "0.11.0" @@ -4212,6 +4201,7 @@ dependencies = [ "bincode", "blake3", "bls12_381 0.8.0", + "bytemuck", "cfg-if", "curve25519-dalek", "elf", @@ -4401,6 +4391,7 @@ dependencies = [ "p3-merkle-tree", "p3-poseidon2", "p3-symmetric", + "p3-util", "serde", "serde_with", "sphinx-core", @@ -4424,8 +4415,11 @@ dependencies = [ name = "sphinx-recursion-gnark-ffi" version = "1.0.0" dependencies = [ + "anyhow", + "bincode", "bindgen", "cfg-if", + "hex", "log", "num-bigint 0.4.5", "p3-baby-bear", @@ -4434,6 +4428,7 @@ dependencies = [ "rand", "serde", "serde_json", + "sha2", "sphinx-core", "sphinx-recursion-compiler", "tempfile", @@ -4496,6 +4491,7 @@ dependencies = [ "strum", "strum_macros", "tempfile", + "thiserror", "tokio", "tracing", "twirp", @@ -4776,12 +4772,13 @@ dependencies = [ ] [[package]] -name = "tokio-native-tls" -version = "0.3.1" +name = "tokio-rustls" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "native-tls", + "rustls", + "rustls-pki-types", "tokio", ] @@ -5064,6 +5061,12 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" version = "2.5.0" @@ -5255,6 +5258,15 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki-roots" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "which" version = "4.4.2" diff --git a/examples/io/script/src/main.rs b/examples/io/script/src/main.rs index e9cfd396d..9ec952de2 100644 --- a/examples/io/script/src/main.rs +++ b/examples/io/script/src/main.rs @@ -1,5 +1,5 @@ use serde::{Deserialize, Serialize}; -use sphinx_sdk::{utils, ProverClient, SphinxStdin}; +use sphinx_sdk::{utils, ProverClient, SphinxProof, SphinxStdin}; /// The ELF we want to execute inside the zkVM. const ELF: &[u8] = include_bytes!("../../program/elf/riscv32im-succinct-zkvm-elf"); @@ -42,10 +42,16 @@ fn main() { // Verify proof. client.verify(&proof, &vk).expect("verification failed"); - // Save the proof. + // Test a round trip of proof serialization and deserialization. proof - .save("proof-with-pis.json") + .save("proof-with-pis.bin") .expect("saving proof failed"); + let deserialized_proof = SphinxProof::load("proof-with-pis.bin").expect("loading proof failed"); + + // Verify the deserialized proof. + client + .verify(&deserialized_proof, &vk) + .expect("verification failed"); println!("successfully generated and verified proof for the program!") } diff --git a/examples/is-prime/script/Cargo.lock b/examples/is-prime/script/Cargo.lock index 547151367..6269b2fb8 100644 --- a/examples/is-prime/script/Cargo.lock +++ b/examples/is-prime/script/Cargo.lock @@ -621,16 +621,16 @@ dependencies = [ [[package]] name = "blake3" -version = "1.5.1" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30cca6d3674597c30ddf2c587bf8d9d65c9a84d2326d941cc79c9842dfe0ef52" +checksum = "e9ec96fe9a81b5e365f9db71fe00edc4fe4ca2cc7dcb7861f0603012a7caa210" dependencies = [ "arrayref", "arrayvec", "cc", "cfg-if", "constant_time_eq", - "rayon", + "rayon-core", ] [[package]] @@ -690,6 +690,12 @@ version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" +[[package]] +name = "bytemuck" +version = "1.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e" + [[package]] name = "byteorder" version = "1.5.0" @@ -1613,21 +1619,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "form_urlencoded" version = "1.2.1" @@ -2081,19 +2072,21 @@ dependencies = [ ] [[package]] -name = "hyper-tls" -version = "0.6.0" +name = "hyper-rustls" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" dependencies = [ - "bytes", - "http-body-util", + "futures-util", + "http 1.1.0", "hyper 1.3.1", "hyper-util", - "native-tls", + "rustls", + "rustls-pki-types", "tokio", - "tokio-native-tls", + "tokio-rustls", "tower-service", + "webpki-roots", ] [[package]] @@ -2321,7 +2314,7 @@ checksum = "6971da4d9c3aa03c3d8f3ff0f4155b534aad021292003895a469716b2a230378" dependencies = [ "base64 0.21.7", "pem", - "ring", + "ring 0.16.20", "serde", "serde_json", "simple_asn1", @@ -2516,24 +2509,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "native-tls" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" -dependencies = [ - "lazy_static", - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - [[package]] name = "nohash-hasher" version = "0.2.0" @@ -2758,50 +2733,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "openssl" -version = "0.10.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" -dependencies = [ - "bitflags 2.5.0", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.63", -] - -[[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "openssl-sys" -version = "0.9.102" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "overload" version = "0.1.1" @@ -3403,6 +3334,53 @@ version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" +[[package]] +name = "quinn" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4ceeeeabace7857413798eb1ffa1e9c905a9946a57d81fb69b4b71c4d8eb3ad" +dependencies = [ + "bytes", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "quinn-proto" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddf517c03a109db8100448a4be38d498df8a210a99fe0e1b9eaf39e78c640efe" +dependencies = [ + "bytes", + "rand", + "ring 0.17.8", + "rustc-hash", + "rustls", + "slab", + "thiserror", + "tinyvec", + "tracing", +] + +[[package]] +name = "quinn-udp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9096629c45860fc7fb143e125eb826b5e721e10be3263160c7d60ca832cf8c46" +dependencies = [ + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.52.0", +] + [[package]] name = "quote" version = "1.0.36" @@ -3589,23 +3567,25 @@ dependencies = [ "http-body 1.0.0", "http-body-util", "hyper 1.3.1", - "hyper-tls", + "hyper-rustls", "hyper-util", "ipnet", "js-sys", "log", "mime", - "native-tls", "once_cell", "percent-encoding", "pin-project-lite", + "quinn", + "rustls", "rustls-pemfile", + "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper 1.0.1", "tokio", - "tokio-native-tls", + "tokio-rustls", "tokio-util", "tower-service", "url", @@ -3613,6 +3593,7 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", + "webpki-roots", "winreg 0.52.0", ] @@ -3651,11 +3632,26 @@ dependencies = [ "libc", "once_cell", "spin 0.5.2", - "untrusted", + "untrusted 0.7.1", "web-sys", "winapi", ] +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin 0.9.8", + "untrusted 0.9.0", + "windows-sys 0.52.0", +] + [[package]] name = "ripemd" version = "0.1.3" @@ -3776,6 +3772,20 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rustls" +version = "0.23.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" +dependencies = [ + "once_cell", + "ring 0.17.8", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + [[package]] name = "rustls-pemfile" version = "2.1.2" @@ -3792,6 +3802,17 @@ version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" +[[package]] +name = "rustls-webpki" +version = "0.102.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e" +dependencies = [ + "ring 0.17.8", + "rustls-pki-types", + "untrusted 0.9.0", +] + [[package]] name = "rustversion" version = "1.0.17" @@ -3867,15 +3888,6 @@ dependencies = [ "sdd", ] -[[package]] -name = "schannel" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" -dependencies = [ - "windows-sys 0.52.0", -] - [[package]] name = "scopeguard" version = "1.2.0" @@ -3914,29 +3926,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "security-framework" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" -dependencies = [ - "bitflags 2.5.0", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "semver" version = "0.11.0" @@ -4210,6 +4199,7 @@ dependencies = [ "bincode", "blake3", "bls12_381 0.8.0", + "bytemuck", "cfg-if", "curve25519-dalek", "elf", @@ -4391,6 +4381,7 @@ dependencies = [ "p3-merkle-tree", "p3-poseidon2", "p3-symmetric", + "p3-util", "serde", "serde_with", "sphinx-core", @@ -4414,8 +4405,11 @@ dependencies = [ name = "sphinx-recursion-gnark-ffi" version = "1.0.0" dependencies = [ + "anyhow", + "bincode", "bindgen", "cfg-if", + "hex", "log", "num-bigint 0.4.5", "p3-baby-bear", @@ -4424,6 +4418,7 @@ dependencies = [ "rand", "serde", "serde_json", + "sha2", "sphinx-core", "sphinx-recursion-compiler", "tempfile", @@ -4486,6 +4481,7 @@ dependencies = [ "strum", "strum_macros", "tempfile", + "thiserror", "tokio", "tracing", "twirp", @@ -4766,12 +4762,13 @@ dependencies = [ ] [[package]] -name = "tokio-native-tls" -version = "0.3.1" +name = "tokio-rustls" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "native-tls", + "rustls", + "rustls-pki-types", "tokio", ] @@ -5054,6 +5051,12 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" version = "2.5.0" @@ -5245,6 +5248,15 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki-roots" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "which" version = "4.4.2" diff --git a/examples/is-prime/script/src/main.rs b/examples/is-prime/script/src/main.rs index e930246a3..5b1f972c1 100644 --- a/examples/is-prime/script/src/main.rs +++ b/examples/is-prime/script/src/main.rs @@ -1,5 +1,5 @@ //! A program that takes a number `n` as input, and writes if `n` is prime as an output. -use sphinx_sdk::{utils, ProverClient, SphinxStdin}; +use sphinx_sdk::{utils, ProverClient, SphinxProof, SphinxStdin}; const ELF: &[u8] = include_bytes!("../../program/elf/riscv32im-succinct-zkvm-elf"); @@ -23,10 +23,17 @@ fn main() { client.verify(&proof, &vk).expect("verification failed"); - // Save the proof + // Test a round trip of proof serialization and deserialization. proof - .save("proof-with-is-prime.json") + .save("proof-with-is-prime.bin") .expect("saving proof failed"); + let deserialized_proof = + SphinxProof::load("proof-with-is-prime.bin").expect("loading proof failed"); + + // Verify the deserialized proof. + client + .verify(&deserialized_proof, &vk) + .expect("verification failed"); println!("successfully generated and verified proof for the program!") } diff --git a/examples/json/program/Cargo.lock b/examples/json/program/Cargo.lock index dcf4b5bbd..020f8c2d8 100644 --- a/examples/json/program/Cargo.lock +++ b/examples/json/program/Cargo.lock @@ -260,6 +260,12 @@ dependencies = [ "signature", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "lib" version = "0.1.0" @@ -462,6 +468,7 @@ dependencies = [ "cfg-if", "getrandom", "k256", + "lazy_static", "once_cell", "rand", "sha2", diff --git a/examples/json/program/elf/riscv32im-succinct-zkvm-elf b/examples/json/program/elf/riscv32im-succinct-zkvm-elf index 103197927..b716c3356 100755 Binary files a/examples/json/program/elf/riscv32im-succinct-zkvm-elf and b/examples/json/program/elf/riscv32im-succinct-zkvm-elf differ diff --git a/examples/json/script/Cargo.lock b/examples/json/script/Cargo.lock index 1dc424fe2..41c216890 100644 --- a/examples/json/script/Cargo.lock +++ b/examples/json/script/Cargo.lock @@ -621,16 +621,16 @@ dependencies = [ [[package]] name = "blake3" -version = "1.5.1" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30cca6d3674597c30ddf2c587bf8d9d65c9a84d2326d941cc79c9842dfe0ef52" +checksum = "e9ec96fe9a81b5e365f9db71fe00edc4fe4ca2cc7dcb7861f0603012a7caa210" dependencies = [ "arrayref", "arrayvec", "cc", "cfg-if", "constant_time_eq", - "rayon", + "rayon-core", ] [[package]] @@ -690,6 +690,12 @@ version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" +[[package]] +name = "bytemuck" +version = "1.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e" + [[package]] name = "byteorder" version = "1.5.0" @@ -1613,21 +1619,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "form_urlencoded" version = "1.2.1" @@ -2081,19 +2072,21 @@ dependencies = [ ] [[package]] -name = "hyper-tls" -version = "0.6.0" +name = "hyper-rustls" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" dependencies = [ - "bytes", - "http-body-util", + "futures-util", + "http 1.1.0", "hyper 1.3.1", "hyper-util", - "native-tls", + "rustls", + "rustls-pki-types", "tokio", - "tokio-native-tls", + "tokio-rustls", "tower-service", + "webpki-roots", ] [[package]] @@ -2325,7 +2318,7 @@ checksum = "6971da4d9c3aa03c3d8f3ff0f4155b534aad021292003895a469716b2a230378" dependencies = [ "base64 0.21.7", "pem", - "ring", + "ring 0.16.20", "serde", "serde_json", "simple_asn1", @@ -2527,24 +2520,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "native-tls" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" -dependencies = [ - "lazy_static", - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - [[package]] name = "nohash-hasher" version = "0.2.0" @@ -2769,50 +2744,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "openssl" -version = "0.10.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" -dependencies = [ - "bitflags 2.5.0", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.63", -] - -[[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "openssl-sys" -version = "0.9.102" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "overload" version = "0.1.1" @@ -3414,6 +3345,53 @@ version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" +[[package]] +name = "quinn" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4ceeeeabace7857413798eb1ffa1e9c905a9946a57d81fb69b4b71c4d8eb3ad" +dependencies = [ + "bytes", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "quinn-proto" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddf517c03a109db8100448a4be38d498df8a210a99fe0e1b9eaf39e78c640efe" +dependencies = [ + "bytes", + "rand", + "ring 0.17.8", + "rustc-hash", + "rustls", + "slab", + "thiserror", + "tinyvec", + "tracing", +] + +[[package]] +name = "quinn-udp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9096629c45860fc7fb143e125eb826b5e721e10be3263160c7d60ca832cf8c46" +dependencies = [ + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.52.0", +] + [[package]] name = "quote" version = "1.0.36" @@ -3600,23 +3578,25 @@ dependencies = [ "http-body 1.0.0", "http-body-util", "hyper 1.3.1", - "hyper-tls", + "hyper-rustls", "hyper-util", "ipnet", "js-sys", "log", "mime", - "native-tls", "once_cell", "percent-encoding", "pin-project-lite", + "quinn", + "rustls", "rustls-pemfile", + "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper 1.0.1", "tokio", - "tokio-native-tls", + "tokio-rustls", "tokio-util", "tower-service", "url", @@ -3624,6 +3604,7 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", + "webpki-roots", "winreg 0.52.0", ] @@ -3662,11 +3643,26 @@ dependencies = [ "libc", "once_cell", "spin 0.5.2", - "untrusted", + "untrusted 0.7.1", "web-sys", "winapi", ] +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin 0.9.8", + "untrusted 0.9.0", + "windows-sys 0.52.0", +] + [[package]] name = "ripemd" version = "0.1.3" @@ -3787,6 +3783,20 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rustls" +version = "0.23.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" +dependencies = [ + "once_cell", + "ring 0.17.8", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + [[package]] name = "rustls-pemfile" version = "2.1.2" @@ -3803,6 +3813,17 @@ version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" +[[package]] +name = "rustls-webpki" +version = "0.102.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e" +dependencies = [ + "ring 0.17.8", + "rustls-pki-types", + "untrusted 0.9.0", +] + [[package]] name = "rustversion" version = "1.0.17" @@ -3878,15 +3899,6 @@ dependencies = [ "sdd", ] -[[package]] -name = "schannel" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" -dependencies = [ - "windows-sys 0.52.0", -] - [[package]] name = "scopeguard" version = "1.2.0" @@ -3925,29 +3937,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "security-framework" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" -dependencies = [ - "bitflags 2.5.0", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "semver" version = "0.11.0" @@ -4221,6 +4210,7 @@ dependencies = [ "bincode", "blake3", "bls12_381 0.8.0", + "bytemuck", "cfg-if", "curve25519-dalek", "elf", @@ -4410,6 +4400,7 @@ dependencies = [ "p3-merkle-tree", "p3-poseidon2", "p3-symmetric", + "p3-util", "serde", "serde_with", "sphinx-core", @@ -4433,8 +4424,11 @@ dependencies = [ name = "sphinx-recursion-gnark-ffi" version = "1.0.0" dependencies = [ + "anyhow", + "bincode", "bindgen", "cfg-if", + "hex", "log", "num-bigint 0.4.5", "p3-baby-bear", @@ -4443,6 +4437,7 @@ dependencies = [ "rand", "serde", "serde_json", + "sha2", "sphinx-core", "sphinx-recursion-compiler", "tempfile", @@ -4505,6 +4500,7 @@ dependencies = [ "strum", "strum_macros", "tempfile", + "thiserror", "tokio", "tracing", "twirp", @@ -4785,12 +4781,13 @@ dependencies = [ ] [[package]] -name = "tokio-native-tls" -version = "0.3.1" +name = "tokio-rustls" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "native-tls", + "rustls", + "rustls-pki-types", "tokio", ] @@ -5073,6 +5070,12 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" version = "2.5.0" @@ -5264,6 +5267,15 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki-roots" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "which" version = "4.4.2" diff --git a/examples/json/script/src/main.rs b/examples/json/script/src/main.rs index 8a5a27136..ee6f9929d 100644 --- a/examples/json/script/src/main.rs +++ b/examples/json/script/src/main.rs @@ -1,7 +1,7 @@ //! A simple script to generate and verify the proof of a given program. use lib::{Account, Transaction}; -use sphinx_sdk::{utils, ProverClient, SphinxStdin}; +use sphinx_sdk::{utils, ProverClient, SphinxProof, SphinxStdin}; const JSON_ELF: &[u8] = include_bytes!("../../program/elf/riscv32im-succinct-zkvm-elf"); @@ -62,10 +62,16 @@ fn main() { // Verify proof. client.verify(&proof, &vk).expect("verification failed"); - // Save proof. + // Test a round trip of proof serialization and deserialization. proof - .save("proof-with-io.json") + .save("proof-with-io.bin") .expect("saving proof failed"); + let deserialized_proof = SphinxProof::load("proof-with-io.bin").expect("loading proof failed"); + + // Verify the deserialized proof. + client + .verify(&deserialized_proof, &vk) + .expect("verification failed"); println!("successfully generated and verified proof for the program!") } diff --git a/examples/regex/program/Cargo.lock b/examples/regex/program/Cargo.lock index 6f517f234..de67e1877 100644 --- a/examples/regex/program/Cargo.lock +++ b/examples/regex/program/Cargo.lock @@ -253,6 +253,12 @@ dependencies = [ "signature", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.154" @@ -474,6 +480,7 @@ dependencies = [ "cfg-if", "getrandom", "k256", + "lazy_static", "once_cell", "rand", "sha2", diff --git a/examples/regex/program/elf/riscv32im-succinct-zkvm-elf b/examples/regex/program/elf/riscv32im-succinct-zkvm-elf index d94ddeba4..eecdaae19 100755 Binary files a/examples/regex/program/elf/riscv32im-succinct-zkvm-elf and b/examples/regex/program/elf/riscv32im-succinct-zkvm-elf differ diff --git a/examples/regex/script/Cargo.lock b/examples/regex/script/Cargo.lock index fe2416eeb..cd92742f4 100644 --- a/examples/regex/script/Cargo.lock +++ b/examples/regex/script/Cargo.lock @@ -621,16 +621,16 @@ dependencies = [ [[package]] name = "blake3" -version = "1.5.1" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30cca6d3674597c30ddf2c587bf8d9d65c9a84d2326d941cc79c9842dfe0ef52" +checksum = "e9ec96fe9a81b5e365f9db71fe00edc4fe4ca2cc7dcb7861f0603012a7caa210" dependencies = [ "arrayref", "arrayvec", "cc", "cfg-if", "constant_time_eq", - "rayon", + "rayon-core", ] [[package]] @@ -690,6 +690,12 @@ version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" +[[package]] +name = "bytemuck" +version = "1.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e" + [[package]] name = "byteorder" version = "1.5.0" @@ -1613,21 +1619,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "form_urlencoded" version = "1.2.1" @@ -2081,19 +2072,21 @@ dependencies = [ ] [[package]] -name = "hyper-tls" -version = "0.6.0" +name = "hyper-rustls" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" dependencies = [ - "bytes", - "http-body-util", + "futures-util", + "http 1.1.0", "hyper 1.3.1", "hyper-util", - "native-tls", + "rustls", + "rustls-pki-types", "tokio", - "tokio-native-tls", + "tokio-rustls", "tower-service", + "webpki-roots", ] [[package]] @@ -2314,7 +2307,7 @@ checksum = "6971da4d9c3aa03c3d8f3ff0f4155b534aad021292003895a469716b2a230378" dependencies = [ "base64 0.21.7", "pem", - "ring", + "ring 0.16.20", "serde", "serde_json", "simple_asn1", @@ -2509,24 +2502,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "native-tls" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" -dependencies = [ - "lazy_static", - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - [[package]] name = "nohash-hasher" version = "0.2.0" @@ -2751,50 +2726,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "openssl" -version = "0.10.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" -dependencies = [ - "bitflags 2.5.0", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.63", -] - -[[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "openssl-sys" -version = "0.9.102" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "overload" version = "0.1.1" @@ -3396,6 +3327,53 @@ version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" +[[package]] +name = "quinn" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4ceeeeabace7857413798eb1ffa1e9c905a9946a57d81fb69b4b71c4d8eb3ad" +dependencies = [ + "bytes", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "quinn-proto" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddf517c03a109db8100448a4be38d498df8a210a99fe0e1b9eaf39e78c640efe" +dependencies = [ + "bytes", + "rand", + "ring 0.17.8", + "rustc-hash", + "rustls", + "slab", + "thiserror", + "tinyvec", + "tracing", +] + +[[package]] +name = "quinn-udp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9096629c45860fc7fb143e125eb826b5e721e10be3263160c7d60ca832cf8c46" +dependencies = [ + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.52.0", +] + [[package]] name = "quote" version = "1.0.36" @@ -3591,23 +3569,25 @@ dependencies = [ "http-body 1.0.0", "http-body-util", "hyper 1.3.1", - "hyper-tls", + "hyper-rustls", "hyper-util", "ipnet", "js-sys", "log", "mime", - "native-tls", "once_cell", "percent-encoding", "pin-project-lite", + "quinn", + "rustls", "rustls-pemfile", + "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper 1.0.1", "tokio", - "tokio-native-tls", + "tokio-rustls", "tokio-util", "tower-service", "url", @@ -3615,6 +3595,7 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", + "webpki-roots", "winreg 0.52.0", ] @@ -3653,11 +3634,26 @@ dependencies = [ "libc", "once_cell", "spin 0.5.2", - "untrusted", + "untrusted 0.7.1", "web-sys", "winapi", ] +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin 0.9.8", + "untrusted 0.9.0", + "windows-sys 0.52.0", +] + [[package]] name = "ripemd" version = "0.1.3" @@ -3778,6 +3774,20 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rustls" +version = "0.23.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" +dependencies = [ + "once_cell", + "ring 0.17.8", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + [[package]] name = "rustls-pemfile" version = "2.1.2" @@ -3794,6 +3804,17 @@ version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" +[[package]] +name = "rustls-webpki" +version = "0.102.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e" +dependencies = [ + "ring 0.17.8", + "rustls-pki-types", + "untrusted 0.9.0", +] + [[package]] name = "rustversion" version = "1.0.17" @@ -3869,15 +3890,6 @@ dependencies = [ "sdd", ] -[[package]] -name = "schannel" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" -dependencies = [ - "windows-sys 0.52.0", -] - [[package]] name = "scopeguard" version = "1.2.0" @@ -3916,29 +3928,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "security-framework" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" -dependencies = [ - "bitflags 2.5.0", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "semver" version = "0.11.0" @@ -4212,6 +4201,7 @@ dependencies = [ "bincode", "blake3", "bls12_381 0.8.0", + "bytemuck", "cfg-if", "curve25519-dalek", "elf", @@ -4401,6 +4391,7 @@ dependencies = [ "p3-merkle-tree", "p3-poseidon2", "p3-symmetric", + "p3-util", "serde", "serde_with", "sphinx-core", @@ -4424,8 +4415,11 @@ dependencies = [ name = "sphinx-recursion-gnark-ffi" version = "1.0.0" dependencies = [ + "anyhow", + "bincode", "bindgen", "cfg-if", + "hex", "log", "num-bigint 0.4.5", "p3-baby-bear", @@ -4434,6 +4428,7 @@ dependencies = [ "rand", "serde", "serde_json", + "sha2", "sphinx-core", "sphinx-recursion-compiler", "tempfile", @@ -4496,6 +4491,7 @@ dependencies = [ "strum", "strum_macros", "tempfile", + "thiserror", "tokio", "tracing", "twirp", @@ -4776,12 +4772,13 @@ dependencies = [ ] [[package]] -name = "tokio-native-tls" -version = "0.3.1" +name = "tokio-rustls" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "native-tls", + "rustls", + "rustls-pki-types", "tokio", ] @@ -5064,6 +5061,12 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" version = "2.5.0" @@ -5255,6 +5258,15 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki-roots" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "which" version = "4.4.2" diff --git a/examples/regex/script/src/main.rs b/examples/regex/script/src/main.rs index 94a89d0f9..82b07e739 100644 --- a/examples/regex/script/src/main.rs +++ b/examples/regex/script/src/main.rs @@ -1,4 +1,4 @@ -use sphinx_sdk::{utils, ProverClient, SphinxStdin}; +use sphinx_sdk::{utils, ProverClient, SphinxProof, SphinxStdin}; /// The ELF we want to execute inside the zkVM. const REGEX_IO_ELF: &[u8] = include_bytes!("../../program/elf/riscv32im-succinct-zkvm-elf"); @@ -29,10 +29,16 @@ fn main() { // Verify proof. client.verify(&proof, &vk).expect("verification failed"); - // Save the proof. + // Test a round trip of proof serialization and deserialization. proof - .save("proof-with-pis.json") + .save("proof-with-pis.bin") .expect("saving proof failed"); + let deserialized_proof = SphinxProof::load("proof-with-pis.bin").expect("loading proof failed"); + + // Verify the deserialized proof. + client + .verify(&deserialized_proof, &vk) + .expect("verification failed"); println!("successfully generated and verified proof for the program!") } diff --git a/examples/rsa/program/Cargo.lock b/examples/rsa/program/Cargo.lock index 5da20e06f..a5f984a58 100644 --- a/examples/rsa/program/Cargo.lock +++ b/examples/rsa/program/Cargo.lock @@ -303,9 +303,9 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" dependencies = [ "spin", ] @@ -627,6 +627,7 @@ dependencies = [ "cfg-if", "getrandom", "k256", + "lazy_static", "once_cell", "rand", "sha2 0.10.8", @@ -635,9 +636,9 @@ dependencies = [ [[package]] name = "spin" -version = "0.5.2" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] name = "spki" diff --git a/examples/rsa/program/elf/riscv32im-succinct-zkvm-elf b/examples/rsa/program/elf/riscv32im-succinct-zkvm-elf index 67e5974de..b7fb76016 100755 Binary files a/examples/rsa/program/elf/riscv32im-succinct-zkvm-elf and b/examples/rsa/program/elf/riscv32im-succinct-zkvm-elf differ diff --git a/examples/rsa/script/Cargo.lock b/examples/rsa/script/Cargo.lock index c87ca0fc3..d06062e6e 100644 --- a/examples/rsa/script/Cargo.lock +++ b/examples/rsa/script/Cargo.lock @@ -621,16 +621,16 @@ dependencies = [ [[package]] name = "blake3" -version = "1.5.1" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30cca6d3674597c30ddf2c587bf8d9d65c9a84d2326d941cc79c9842dfe0ef52" +checksum = "e9ec96fe9a81b5e365f9db71fe00edc4fe4ca2cc7dcb7861f0603012a7caa210" dependencies = [ "arrayref", "arrayvec", "cc", "cfg-if", "constant_time_eq", - "rayon", + "rayon-core", ] [[package]] @@ -690,6 +690,12 @@ version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" +[[package]] +name = "bytemuck" +version = "1.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e" + [[package]] name = "byteorder" version = "1.5.0" @@ -1640,21 +1646,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "form_urlencoded" version = "1.2.1" @@ -2108,19 +2099,21 @@ dependencies = [ ] [[package]] -name = "hyper-tls" -version = "0.6.0" +name = "hyper-rustls" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" dependencies = [ - "bytes", - "http-body-util", + "futures-util", + "http 1.1.0", "hyper 1.3.1", "hyper-util", - "native-tls", + "rustls", + "rustls-pki-types", "tokio", - "tokio-native-tls", + "tokio-rustls", "tower-service", + "webpki-roots", ] [[package]] @@ -2341,7 +2334,7 @@ checksum = "6971da4d9c3aa03c3d8f3ff0f4155b534aad021292003895a469716b2a230378" dependencies = [ "base64 0.21.7", "pem", - "ring", + "ring 0.16.20", "serde", "serde_json", "simple_asn1", @@ -2536,24 +2529,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "native-tls" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" -dependencies = [ - "lazy_static", - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - [[package]] name = "nohash-hasher" version = "0.2.0" @@ -2795,50 +2770,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "openssl" -version = "0.10.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" -dependencies = [ - "bitflags 2.5.0", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.63", -] - -[[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "openssl-sys" -version = "0.9.102" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "overload" version = "0.1.1" @@ -3471,6 +3402,53 @@ version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" +[[package]] +name = "quinn" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4ceeeeabace7857413798eb1ffa1e9c905a9946a57d81fb69b4b71c4d8eb3ad" +dependencies = [ + "bytes", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "quinn-proto" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddf517c03a109db8100448a4be38d498df8a210a99fe0e1b9eaf39e78c640efe" +dependencies = [ + "bytes", + "rand", + "ring 0.17.8", + "rustc-hash", + "rustls", + "slab", + "thiserror", + "tinyvec", + "tracing", +] + +[[package]] +name = "quinn-udp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9096629c45860fc7fb143e125eb826b5e721e10be3263160c7d60ca832cf8c46" +dependencies = [ + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.52.0", +] + [[package]] name = "quote" version = "1.0.36" @@ -3657,23 +3635,25 @@ dependencies = [ "http-body 1.0.0", "http-body-util", "hyper 1.3.1", - "hyper-tls", + "hyper-rustls", "hyper-util", "ipnet", "js-sys", "log", "mime", - "native-tls", "once_cell", "percent-encoding", "pin-project-lite", + "quinn", + "rustls", "rustls-pemfile", + "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper 1.0.1", "tokio", - "tokio-native-tls", + "tokio-rustls", "tokio-util", "tower-service", "url", @@ -3681,6 +3661,7 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", + "webpki-roots", "winreg 0.52.0", ] @@ -3719,11 +3700,26 @@ dependencies = [ "libc", "once_cell", "spin 0.5.2", - "untrusted", + "untrusted 0.7.1", "web-sys", "winapi", ] +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin 0.9.8", + "untrusted 0.9.0", + "windows-sys 0.52.0", +] + [[package]] name = "ripemd" version = "0.1.3" @@ -3873,6 +3869,20 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rustls" +version = "0.23.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" +dependencies = [ + "once_cell", + "ring 0.17.8", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + [[package]] name = "rustls-pemfile" version = "2.1.2" @@ -3889,6 +3899,17 @@ version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" +[[package]] +name = "rustls-webpki" +version = "0.102.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e" +dependencies = [ + "ring 0.17.8", + "rustls-pki-types", + "untrusted 0.9.0", +] + [[package]] name = "rustversion" version = "1.0.17" @@ -3964,15 +3985,6 @@ dependencies = [ "sdd", ] -[[package]] -name = "schannel" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" -dependencies = [ - "windows-sys 0.52.0", -] - [[package]] name = "scopeguard" version = "1.2.0" @@ -4011,29 +4023,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "security-framework" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" -dependencies = [ - "bitflags 2.5.0", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "semver" version = "0.11.0" @@ -4307,6 +4296,7 @@ dependencies = [ "bincode", "blake3", "bls12_381 0.8.0", + "bytemuck", "cfg-if", "curve25519-dalek", "elf", @@ -4496,6 +4486,7 @@ dependencies = [ "p3-merkle-tree", "p3-poseidon2", "p3-symmetric", + "p3-util", "serde", "serde_with", "sphinx-core", @@ -4519,8 +4510,11 @@ dependencies = [ name = "sphinx-recursion-gnark-ffi" version = "1.0.0" dependencies = [ + "anyhow", + "bincode", "bindgen", "cfg-if", + "hex", "log", "num-bigint 0.4.5", "p3-baby-bear", @@ -4529,6 +4523,7 @@ dependencies = [ "rand", "serde", "serde_json", + "sha2", "sphinx-core", "sphinx-recursion-compiler", "tempfile", @@ -4591,6 +4586,7 @@ dependencies = [ "strum", "strum_macros", "tempfile", + "thiserror", "tokio", "tracing", "twirp", @@ -4881,12 +4877,13 @@ dependencies = [ ] [[package]] -name = "tokio-native-tls" -version = "0.3.1" +name = "tokio-rustls" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "native-tls", + "rustls", + "rustls-pki-types", "tokio", ] @@ -5169,6 +5166,12 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" version = "2.5.0" @@ -5360,6 +5363,15 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki-roots" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "which" version = "4.4.2" diff --git a/examples/rsa/script/src/main.rs b/examples/rsa/script/src/main.rs index 3c4fecd46..e0217b63b 100644 --- a/examples/rsa/script/src/main.rs +++ b/examples/rsa/script/src/main.rs @@ -2,7 +2,7 @@ use rsa::{ pkcs8::{DecodePrivateKey, DecodePublicKey}, RsaPrivateKey, RsaPublicKey, }; -use sphinx_sdk::{utils, ProverClient, SphinxStdin}; +use sphinx_sdk::{utils, ProverClient, SphinxProof, SphinxStdin}; use std::vec; /// The ELF we want to execute inside the zkVM. @@ -59,10 +59,14 @@ fn main() { // Verify proof. client.verify(&proof, &vk).expect("verification failed"); - // Save the proof. - proof - .save("proof-with-pis.json") - .expect("saving proof failed"); + // Test a round trip of proof serialization and deserialization. + proof.save("proof-with-pis").expect("saving proof failed"); + let deserialized_proof = SphinxProof::load("proof-with-pis").expect("loading proof failed"); + + // Verify the deserialized proof. + client + .verify(&deserialized_proof, &vk) + .expect("verification failed"); println!("successfully generated and verified proof for the program!") } diff --git a/examples/ssz-withdrawals/program/Cargo.lock b/examples/ssz-withdrawals/program/Cargo.lock index df38e75af..defe35ed6 100644 --- a/examples/ssz-withdrawals/program/Cargo.lock +++ b/examples/ssz-withdrawals/program/Cargo.lock @@ -814,9 +814,9 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" @@ -1365,6 +1365,7 @@ dependencies = [ "cfg-if", "getrandom", "k256", + "lazy_static", "once_cell", "rand", "sha2 0.10.8", diff --git a/examples/ssz-withdrawals/program/elf/riscv32im-succinct-zkvm-elf b/examples/ssz-withdrawals/program/elf/riscv32im-succinct-zkvm-elf index 19358a651..8f11d2fdb 100755 Binary files a/examples/ssz-withdrawals/program/elf/riscv32im-succinct-zkvm-elf and b/examples/ssz-withdrawals/program/elf/riscv32im-succinct-zkvm-elf differ diff --git a/examples/ssz-withdrawals/script/Cargo.lock b/examples/ssz-withdrawals/script/Cargo.lock index 19d5b1381..4ef36f593 100644 --- a/examples/ssz-withdrawals/script/Cargo.lock +++ b/examples/ssz-withdrawals/script/Cargo.lock @@ -621,16 +621,16 @@ dependencies = [ [[package]] name = "blake3" -version = "1.5.1" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30cca6d3674597c30ddf2c587bf8d9d65c9a84d2326d941cc79c9842dfe0ef52" +checksum = "e9ec96fe9a81b5e365f9db71fe00edc4fe4ca2cc7dcb7861f0603012a7caa210" dependencies = [ "arrayref", "arrayvec", "cc", "cfg-if", "constant_time_eq", - "rayon", + "rayon-core", ] [[package]] @@ -690,6 +690,12 @@ version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" +[[package]] +name = "bytemuck" +version = "1.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e" + [[package]] name = "byteorder" version = "1.5.0" @@ -1613,21 +1619,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "form_urlencoded" version = "1.2.1" @@ -2081,19 +2072,21 @@ dependencies = [ ] [[package]] -name = "hyper-tls" -version = "0.6.0" +name = "hyper-rustls" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" dependencies = [ - "bytes", - "http-body-util", + "futures-util", + "http 1.1.0", "hyper 1.3.1", "hyper-util", - "native-tls", + "rustls", + "rustls-pki-types", "tokio", - "tokio-native-tls", + "tokio-rustls", "tower-service", + "webpki-roots", ] [[package]] @@ -2314,7 +2307,7 @@ checksum = "6971da4d9c3aa03c3d8f3ff0f4155b534aad021292003895a469716b2a230378" dependencies = [ "base64 0.21.7", "pem", - "ring", + "ring 0.16.20", "serde", "serde_json", "simple_asn1", @@ -2509,24 +2502,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "native-tls" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" -dependencies = [ - "lazy_static", - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - [[package]] name = "nohash-hasher" version = "0.2.0" @@ -2751,50 +2726,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "openssl" -version = "0.10.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" -dependencies = [ - "bitflags 2.5.0", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.63", -] - -[[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "openssl-sys" -version = "0.9.102" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "overload" version = "0.1.1" @@ -3396,6 +3327,53 @@ version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" +[[package]] +name = "quinn" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4ceeeeabace7857413798eb1ffa1e9c905a9946a57d81fb69b4b71c4d8eb3ad" +dependencies = [ + "bytes", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "quinn-proto" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddf517c03a109db8100448a4be38d498df8a210a99fe0e1b9eaf39e78c640efe" +dependencies = [ + "bytes", + "rand", + "ring 0.17.8", + "rustc-hash", + "rustls", + "slab", + "thiserror", + "tinyvec", + "tracing", +] + +[[package]] +name = "quinn-udp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9096629c45860fc7fb143e125eb826b5e721e10be3263160c7d60ca832cf8c46" +dependencies = [ + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.52.0", +] + [[package]] name = "quote" version = "1.0.36" @@ -3582,23 +3560,25 @@ dependencies = [ "http-body 1.0.0", "http-body-util", "hyper 1.3.1", - "hyper-tls", + "hyper-rustls", "hyper-util", "ipnet", "js-sys", "log", "mime", - "native-tls", "once_cell", "percent-encoding", "pin-project-lite", + "quinn", + "rustls", "rustls-pemfile", + "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper 1.0.1", "tokio", - "tokio-native-tls", + "tokio-rustls", "tokio-util", "tower-service", "url", @@ -3606,6 +3586,7 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", + "webpki-roots", "winreg 0.52.0", ] @@ -3644,11 +3625,26 @@ dependencies = [ "libc", "once_cell", "spin 0.5.2", - "untrusted", + "untrusted 0.7.1", "web-sys", "winapi", ] +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin 0.9.8", + "untrusted 0.9.0", + "windows-sys 0.52.0", +] + [[package]] name = "ripemd" version = "0.1.3" @@ -3769,6 +3765,20 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rustls" +version = "0.23.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" +dependencies = [ + "once_cell", + "ring 0.17.8", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + [[package]] name = "rustls-pemfile" version = "2.1.2" @@ -3785,6 +3795,17 @@ version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" +[[package]] +name = "rustls-webpki" +version = "0.102.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e" +dependencies = [ + "ring 0.17.8", + "rustls-pki-types", + "untrusted 0.9.0", +] + [[package]] name = "rustversion" version = "1.0.17" @@ -3860,15 +3881,6 @@ dependencies = [ "sdd", ] -[[package]] -name = "schannel" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" -dependencies = [ - "windows-sys 0.52.0", -] - [[package]] name = "scopeguard" version = "1.2.0" @@ -3907,29 +3919,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "security-framework" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" -dependencies = [ - "bitflags 2.5.0", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "semver" version = "0.11.0" @@ -4203,6 +4192,7 @@ dependencies = [ "bincode", "blake3", "bls12_381 0.8.0", + "bytemuck", "cfg-if", "curve25519-dalek", "elf", @@ -4392,6 +4382,7 @@ dependencies = [ "p3-merkle-tree", "p3-poseidon2", "p3-symmetric", + "p3-util", "serde", "serde_with", "sphinx-core", @@ -4415,8 +4406,11 @@ dependencies = [ name = "sphinx-recursion-gnark-ffi" version = "1.0.0" dependencies = [ + "anyhow", + "bincode", "bindgen", "cfg-if", + "hex", "log", "num-bigint 0.4.5", "p3-baby-bear", @@ -4425,6 +4419,7 @@ dependencies = [ "rand", "serde", "serde_json", + "sha2", "sphinx-core", "sphinx-recursion-compiler", "tempfile", @@ -4487,6 +4482,7 @@ dependencies = [ "strum", "strum_macros", "tempfile", + "thiserror", "tokio", "tracing", "twirp", @@ -4776,12 +4772,13 @@ dependencies = [ ] [[package]] -name = "tokio-native-tls" -version = "0.3.1" +name = "tokio-rustls" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "native-tls", + "rustls", + "rustls-pki-types", "tokio", ] @@ -5064,6 +5061,12 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" version = "2.5.0" @@ -5255,6 +5258,15 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki-roots" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "which" version = "4.4.2" diff --git a/examples/ssz-withdrawals/script/src/main.rs b/examples/ssz-withdrawals/script/src/main.rs index 053e747ee..fab9cf097 100644 --- a/examples/ssz-withdrawals/script/src/main.rs +++ b/examples/ssz-withdrawals/script/src/main.rs @@ -1,4 +1,4 @@ -use sphinx_sdk::{utils, ProverClient, SphinxStdin}; +use sphinx_sdk::{utils, ProverClient, SphinxProof, SphinxStdin}; const ELF: &[u8] = include_bytes!("../../program/elf/riscv32im-succinct-zkvm-elf"); @@ -10,17 +10,21 @@ fn main() { let stdin = SphinxStdin::new(); let client = ProverClient::new(); let (pk, vk) = client.setup(ELF); - let proof = client.prove_compressed(&pk, stdin).expect("proving failed"); + let proof = client.prove(&pk, stdin).expect("proving failed"); // Verify proof. - client - .verify_compressed(&proof, &vk) - .expect("verification failed"); + client.verify(&proof, &vk).expect("verification failed"); - // Save proof. + // Test a round trip of proof serialization and deserialization. proof - .save("proof-with-pis.json") + .save("proof-with-pis.bin") .expect("saving proof failed"); + let deserialized_proof = SphinxProof::load("proof-with-pis.bin").expect("loading proof failed"); + + // Verify the deserialized proof. + client + .verify(&deserialized_proof, &vk) + .expect("verification failed"); println!("successfully generated and verified proof for the program!") } diff --git a/examples/tendermint/program/Cargo.lock b/examples/tendermint/program/Cargo.lock index c0d32c255..691916f4b 100644 --- a/examples/tendermint/program/Cargo.lock +++ b/examples/tendermint/program/Cargo.lock @@ -440,6 +440,12 @@ dependencies = [ "signature", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.154" @@ -765,6 +771,7 @@ dependencies = [ "cfg-if", "getrandom", "k256", + "lazy_static", "once_cell", "rand", "sha2 0.10.8", diff --git a/examples/tendermint/program/elf/riscv32im-succinct-zkvm-elf b/examples/tendermint/program/elf/riscv32im-succinct-zkvm-elf index d24831bd4..aa374c87a 100755 Binary files a/examples/tendermint/program/elf/riscv32im-succinct-zkvm-elf and b/examples/tendermint/program/elf/riscv32im-succinct-zkvm-elf differ diff --git a/examples/tendermint/script/Cargo.lock b/examples/tendermint/script/Cargo.lock index 5f0cc6ee3..0c7da30eb 100644 --- a/examples/tendermint/script/Cargo.lock +++ b/examples/tendermint/script/Cargo.lock @@ -621,16 +621,16 @@ dependencies = [ [[package]] name = "blake3" -version = "1.5.1" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30cca6d3674597c30ddf2c587bf8d9d65c9a84d2326d941cc79c9842dfe0ef52" +checksum = "e9ec96fe9a81b5e365f9db71fe00edc4fe4ca2cc7dcb7861f0603012a7caa210" dependencies = [ "arrayref", "arrayvec", "cc", "cfg-if", "constant_time_eq", - "rayon", + "rayon-core", ] [[package]] @@ -699,6 +699,12 @@ version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" +[[package]] +name = "bytemuck" +version = "1.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e" + [[package]] name = "byteorder" version = "1.5.0" @@ -2141,32 +2147,34 @@ dependencies = [ ] [[package]] -name = "hyper-tls" -version = "0.5.0" +name = "hyper-rustls" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" dependencies = [ - "bytes", - "hyper 0.14.29", - "native-tls", + "futures-util", + "http 1.1.0", + "hyper 1.3.1", + "hyper-util", + "rustls", + "rustls-pki-types", "tokio", - "tokio-native-tls", + "tokio-rustls", + "tower-service", + "webpki-roots", ] [[package]] name = "hyper-tls" -version = "0.6.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ "bytes", - "http-body-util", - "hyper 1.3.1", - "hyper-util", + "hyper 0.14.29", "native-tls", "tokio", "tokio-native-tls", - "tower-service", ] [[package]] @@ -2387,7 +2395,7 @@ checksum = "6971da4d9c3aa03c3d8f3ff0f4155b534aad021292003895a469716b2a230378" dependencies = [ "base64 0.21.7", "pem", - "ring", + "ring 0.16.20", "serde", "serde_json", "simple_asn1", @@ -3495,6 +3503,53 @@ version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" +[[package]] +name = "quinn" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4ceeeeabace7857413798eb1ffa1e9c905a9946a57d81fb69b4b71c4d8eb3ad" +dependencies = [ + "bytes", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "quinn-proto" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddf517c03a109db8100448a4be38d498df8a210a99fe0e1b9eaf39e78c640efe" +dependencies = [ + "bytes", + "rand", + "ring 0.17.8", + "rustc-hash", + "rustls", + "slab", + "thiserror", + "tinyvec", + "tracing", +] + +[[package]] +name = "quinn-udp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9096629c45860fc7fb143e125eb826b5e721e10be3263160c7d60ca832cf8c46" +dependencies = [ + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.52.0", +] + [[package]] name = "quote" version = "1.0.36" @@ -3646,7 +3701,7 @@ dependencies = [ "http 0.2.12", "http-body 0.4.6", "hyper 0.14.29", - "hyper-tls 0.5.0", + "hyper-tls", "ipnet", "js-sys", "log", @@ -3685,23 +3740,25 @@ dependencies = [ "http-body 1.0.0", "http-body-util", "hyper 1.3.1", - "hyper-tls 0.6.0", + "hyper-rustls", "hyper-util", "ipnet", "js-sys", "log", "mime", - "native-tls", "once_cell", "percent-encoding", "pin-project-lite", + "quinn", + "rustls", "rustls-pemfile 2.1.2", + "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper 1.0.1", "tokio", - "tokio-native-tls", + "tokio-rustls", "tokio-util", "tower-service", "url", @@ -3709,6 +3766,7 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", + "webpki-roots", "winreg 0.52.0", ] @@ -3747,11 +3805,26 @@ dependencies = [ "libc", "once_cell", "spin 0.5.2", - "untrusted", + "untrusted 0.7.1", "web-sys", "winapi", ] +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin 0.9.8", + "untrusted 0.9.0", + "windows-sys 0.52.0", +] + [[package]] name = "ripemd" version = "0.1.3" @@ -3872,6 +3945,20 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rustls" +version = "0.23.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" +dependencies = [ + "once_cell", + "ring 0.17.8", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + [[package]] name = "rustls-pemfile" version = "1.0.4" @@ -3897,6 +3984,17 @@ version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" +[[package]] +name = "rustls-webpki" +version = "0.102.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e" +dependencies = [ + "ring 0.17.8", + "rustls-pki-types", + "untrusted 0.9.0", +] + [[package]] name = "rustversion" version = "1.0.17" @@ -4358,6 +4456,7 @@ dependencies = [ "bincode", "blake3", "bls12_381 0.8.0", + "bytemuck", "cfg-if", "curve25519-dalek", "elf", @@ -4547,6 +4646,7 @@ dependencies = [ "p3-merkle-tree", "p3-poseidon2", "p3-symmetric", + "p3-util", "serde", "serde_with", "sphinx-core", @@ -4570,8 +4670,11 @@ dependencies = [ name = "sphinx-recursion-gnark-ffi" version = "1.0.0" dependencies = [ + "anyhow", + "bincode", "bindgen", "cfg-if", + "hex", "log", "num-bigint 0.4.5", "p3-baby-bear", @@ -4580,6 +4683,7 @@ dependencies = [ "rand", "serde", "serde_json", + "sha2 0.10.8", "sphinx-core", "sphinx-recursion-compiler", "tempfile", @@ -4642,6 +4746,7 @@ dependencies = [ "strum", "strum_macros", "tempfile", + "thiserror", "tokio", "tracing", "twirp", @@ -5016,6 +5121,17 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +dependencies = [ + "rustls", + "rustls-pki-types", + "tokio", +] + [[package]] name = "tokio-util" version = "0.7.11" @@ -5295,6 +5411,12 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" version = "2.5.0" @@ -5486,6 +5608,15 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki-roots" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "which" version = "4.4.2" diff --git a/examples/tendermint/script/Cargo.toml b/examples/tendermint/script/Cargo.toml index 9294e71a0..8a56efbb2 100644 --- a/examples/tendermint/script/Cargo.toml +++ b/examples/tendermint/script/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" [dependencies] sphinx-core = { path = "../../../core", features = ["neon"] } sphinx-sdk = { path = "../../../sdk" } -reqwest = { version = "0.11", features = ["json"] } +reqwest = { version = "0.11", features = ["json", "rustls-tls"] } tokio = { version = "1", features = ["full"] } serde_json = { version = "1.0", default-features = false, features = ["alloc"] } serde = { version = "1.0", default-features = false, features = ["derive"] } diff --git a/examples/tendermint/script/src/main.rs b/examples/tendermint/script/src/main.rs index 0115f8dfd..1771d6fef 100644 --- a/examples/tendermint/script/src/main.rs +++ b/examples/tendermint/script/src/main.rs @@ -1,3 +1,4 @@ +use sphinx_sdk::SphinxProof; use std::time::Duration; use tokio::runtime::Runtime; @@ -62,12 +63,10 @@ fn main() { let client = ProverClient::new(); let (pk, vk) = client.setup(TENDERMINT_ELF); - let proof = client.prove_compressed(&pk, stdin).expect("proving failed"); + let proof = client.prove(&pk, stdin).expect("proving failed"); // Verify proof. - client - .verify_compressed(&proof, &vk) - .expect("verification failed"); + client.verify(&proof, &vk).expect("verification failed"); // Verify the public values let mut expected_public_values: Vec = Vec::new(); @@ -75,15 +74,18 @@ fn main() { expected_public_values.extend(light_block_2.signed_header.header.hash().as_bytes()); expected_public_values.extend(serde_cbor::to_vec(&expected_verdict).unwrap()); - assert_eq!( - proof.public_values.as_ref(), - expected_public_values - ); + assert_eq!(proof.public_values.as_ref(), expected_public_values); - // Save proof. + // Test a round trip of proof serialization and deserialization. proof - .save("proof-with-pis.json") + .save("proof-with-pis.bin") .expect("saving proof failed"); + let deserialized_proof = SphinxProof::load("proof-with-pis.bin").expect("loading proof failed"); + + // Verify the deserialized proof. + client + .verify(&deserialized_proof, &vk) + .expect("verification failed"); println!("successfully generated and verified proof for the program!") } diff --git a/prover/Cargo.toml b/prover/Cargo.toml index 2d3c8ce40..389ba2dd5 100644 --- a/prover/Cargo.toml +++ b/prover/Cargo.toml @@ -34,7 +34,7 @@ anyhow = { workspace = true } size = { workspace = true } tempfile = { workspace = true } tokio = { workspace = true, features = ["full"] } -reqwest = { workspace = true, features = ["default-tls", "trust-dns", "stream"] } +reqwest = { workspace = true, features = ["rustls-tls", "trust-dns", "stream"] } indicatif = { workspace = true } futures = { workspace = true } subtle-encoding = { workspace = true } diff --git a/prover/Makefile b/prover/Makefile index ac2265104..24c506c4a 100644 --- a/prover/Makefile +++ b/prover/Makefile @@ -10,8 +10,9 @@ build-plonk-bn254: --build-dir=./build release-plonk-bn254: - bash release.sh + @read -p "Release version (ex. v1.0.0-testnet)? " version; \ + bash release.sh $$version test-e2e: RUSTFLAGS='-C target-cpu=native' \ - cargo test --package sphinx-prover --lib --release -- tests::test_e2e --exact --show-output \ No newline at end of file + cargo test --package sphinx-prover --lib --release -- tests::test_e2e --exact --show-output diff --git a/prover/src/build.rs b/prover/src/build.rs index 0fc7c51b1..2f0dbaf47 100644 --- a/prover/src/build.rs +++ b/prover/src/build.rs @@ -12,9 +12,9 @@ use sphinx_recursion_core::air::RecursionPublicValues; pub use sphinx_recursion_core::stark::utils::sphinx_dev_mode; use sphinx_recursion_gnark_ffi::PlonkBn254Prover; -use crate::install::{install_plonk_bn254_artifacts, PLONK_BN254_ARTIFACTS_COMMIT}; +use crate::install::install_plonk_bn254_artifacts; use crate::utils::{babybear_bytes_to_bn254, babybears_to_bn254, words_to_bytes}; -use crate::{OuterSC, SphinxProver}; +use crate::{OuterSC, SphinxProver, SPHINX_CIRCUIT_VERSION}; /// Tries to install the PLONK artifacts if they are not already installed. pub fn try_install_plonk_bn254_artifacts(use_aws_cli: bool) -> PathBuf { @@ -27,8 +27,8 @@ pub fn try_install_plonk_bn254_artifacts(use_aws_cli: bool) -> PathBuf { ); } else { println!( - "[sp1] plonk bn254 artifacts for commit {} do not exist at {}. downloading...", - PLONK_BN254_ARTIFACTS_COMMIT, + "[sp1] plonk bn254 artifacts for version {} do not exist at {}. downloading...", + SPHINX_CIRCUIT_VERSION, build_dir.display() ); install_plonk_bn254_artifacts(&build_dir, use_aws_cli); @@ -54,7 +54,7 @@ fn plonk_bn254_artifacts_dir() -> PathBuf { .join(".sp1") .join("circuits") .join("plonk_bn254") - .join(PLONK_BN254_ARTIFACTS_COMMIT) + .join(SPHINX_CIRCUIT_VERSION) } /// Gets the directory where the PLONK artifacts are installed in development mode. diff --git a/prover/src/install.rs b/prover/src/install.rs index 28bb0f469..c898c0b39 100644 --- a/prover/src/install.rs +++ b/prover/src/install.rs @@ -9,14 +9,11 @@ use futures::StreamExt; use indicatif::{ProgressBar, ProgressStyle}; use reqwest::Client; -use crate::utils::block_on; +use crate::{utils::block_on, SPHINX_CIRCUIT_VERSION}; /// The base URL for the S3 bucket containing the plonk bn254 artifacts. pub const PLONK_BN254_ARTIFACTS_URL_BASE: &str = "https://sphinx-plonk-params.s3.amazonaws.com"; -/// The current version of the plonk bn254 artifacts. -pub const PLONK_BN254_ARTIFACTS_COMMIT: &str = "sphinx_dev"; - /// Install the latest plonk bn254 artifacts. /// /// This function will download the latest plonk bn254 artifacts from the S3 bucket and extract them to @@ -28,7 +25,7 @@ pub fn install_plonk_bn254_artifacts(build_dir: &Path, use_aws_cli: bool) { // Download the artifacts. let download_url = format!( "{}/{}.tar.gz", - PLONK_BN254_ARTIFACTS_URL_BASE, PLONK_BN254_ARTIFACTS_COMMIT + PLONK_BN254_ARTIFACTS_URL_BASE, SPHINX_CIRCUIT_VERSION ); let mut artifacts_tar_gz_file = tempfile::NamedTempFile::new().expect("failed to create tempfile"); @@ -74,7 +71,7 @@ pub fn install_plonk_bn254_artifacts_dir() -> PathBuf { .unwrap() .join(".sp1") .join("circuits") - .join(PLONK_BN254_ARTIFACTS_COMMIT) + .join(SPHINX_CIRCUIT_VERSION) } /// Download the file with a progress bar that indicates the progress. diff --git a/prover/src/lib.rs b/prover/src/lib.rs index e538da87f..51858b2f2 100644 --- a/prover/src/lib.rs +++ b/prover/src/lib.rs @@ -15,6 +15,7 @@ pub mod verify; use std::borrow::Borrow; use std::path::Path; +use std::sync::Arc; use p3_baby_bear::BabyBear; use p3_challenger::CanObserve; @@ -55,12 +56,14 @@ pub use sphinx_recursion_program::machine::{ SphinxRootMemoryLayout, }; use tracing::instrument; -use types::{ +pub use types::{ SphinxCoreProof, SphinxCoreProofData, SphinxProvingKey, SphinxRecursionProverError, SphinxReduceProof, SphinxVerifyingKey, }; use utils::words_to_bytes; +pub use sphinx_core::SPHINX_CIRCUIT_VERSION; + /// The configuration for the core prover. pub type CoreSC = BabyBearPoseidon2; @@ -136,6 +139,12 @@ pub struct SphinxProver { /// The machine used for proving the wrapping step. pub wrap_machine: StarkMachine::Val>>, + + /// The options for the core prover. + pub core_opts: SphinxCoreOpts, + + /// The options for the recursion prover. + pub recursion_opts: SphinxCoreOpts, } impl SphinxProver { @@ -194,6 +203,8 @@ impl SphinxProver { compress_machine, shrink_machine, wrap_machine, + core_opts: SphinxCoreOpts::default(), + recursion_opts: SphinxCoreOpts::recursion(), } } @@ -241,9 +252,13 @@ impl SphinxProver { ) -> Result { let config = CoreSC::default(); let program = Program::from(&pk.elf); - let opts = SphinxCoreOpts::default(); - let (proof, public_values_stream) = - sphinx_core::utils::prove(&program, stdin, config, opts)?; + let (proof, public_values_stream) = sphinx_core::utils::prove_with_subproof_verifier( + &program, + stdin, + config, + self.core_opts, + &Some(Arc::new(self)), + )?; let public_values = SphinxPublicValues::from(&public_values_stream); Ok(SphinxCoreProof { proof: SphinxCoreProofData(proof.shard_proofs), @@ -396,44 +411,25 @@ impl SphinxProver { batch_size, ); - let mut first_layer_proofs = Vec::new(); - let opts = SphinxCoreOpts::recursion(); + let mut reduce_proofs = Vec::new(); + let opts = self.recursion_opts; // We want the ability to set SHARD_BATCH_SIZE to 0 to run everything in one chunk let shard_batch_size = if opts.shard_batch_size > 0 { opts.shard_batch_size } else { usize::MAX }; + for inputs in core_inputs.chunks(shard_batch_size) { let proofs = inputs .into_par_iter() .map(|input| { - let mut runtime = RecursionRuntime::, Challenge, _>::new( - &self.recursion_program, - self.compress_machine.config().perm.clone(), - ); - - let mut witness_stream = Vec::new(); - witness_stream.extend(input.write()); - - runtime.witness_stream = witness_stream.into(); - runtime.run(); - runtime.print_stats(); - - let pk = &self.rec_pk; - let mut recursive_challenger = self.compress_machine.config().challenger(); - ( - self.compress_machine.prove::>( - pk, - runtime.record, - &mut recursive_challenger, - opts, - ), - ReduceProgramType::Core, - ) + let proof = + self.compress_machine_proof(input, &self.recursion_program, &self.rec_pk); + (proof, ReduceProgramType::Core) }) .collect::>(); - first_layer_proofs.extend(proofs); + reduce_proofs.extend(proofs); } // Run the deferred proofs programs. @@ -441,40 +437,17 @@ impl SphinxProver { let proofs = inputs .into_par_iter() .map(|input| { - let mut runtime = RecursionRuntime::, Challenge, _>::new( + let proof = self.compress_machine_proof( + input, &self.deferred_program, - self.compress_machine.config().perm.clone(), + &self.deferred_pk, ); - - let mut witness_stream = Vec::new(); - witness_stream.extend(input.write()); - - runtime.witness_stream = witness_stream.into(); - runtime.run(); - runtime.print_stats(); - - let pk = &self.deferred_pk; - let mut recursive_challenger = self.compress_machine.config().challenger(); - ( - self.compress_machine.prove::>( - pk, - runtime.record, - &mut recursive_challenger, - opts, - ), - ReduceProgramType::Deferred, - ) + (proof, ReduceProgramType::Deferred) }) .collect::>(); - first_layer_proofs.extend(proofs); + reduce_proofs.extend(proofs); } - // Chain all the individual shard proofs. - let mut reduce_proofs = first_layer_proofs - .into_iter() - .flat_map(|(proof, kind)| proof.shard_proofs.into_iter().map(move |p| (p, kind))) - .collect::>(); - // Iterate over the recursive proof batches until there is one proof remaining. let mut is_complete; loop { @@ -542,7 +515,7 @@ impl SphinxProver { runtime.run(); runtime.print_stats(); - let opts = SphinxCoreOpts::recursion(); + let opts = self.recursion_opts; let mut recursive_challenger = self.compress_machine.config().challenger(); self.compress_machine .prove::>(pk, runtime.record, &mut recursive_challenger, opts) @@ -579,7 +552,7 @@ impl SphinxProver { tracing::debug!("Compress program executed successfully"); // Prove the compress program. - let opts = SphinxCoreOpts::recursion(); + let opts = self.recursion_opts; let mut compress_challenger = self.shrink_machine.config().challenger(); let mut compress_proof = self.shrink_machine.prove::>( &self.shrink_pk, @@ -620,7 +593,7 @@ impl SphinxProver { tracing::debug!("Wrap program executed successfully"); // Prove the wrap program. - let opts = SphinxCoreOpts::recursion(); + let opts = self.recursion_opts; let mut wrap_challenger = self.wrap_machine.config().challenger(); let time = std::time::Instant::now(); let mut wrap_proof = self.wrap_machine.prove::>( @@ -710,11 +683,11 @@ mod tests { use std::fs::File; use std::io::{Read, Write}; - use self::build::try_build_plonk_bn254_artifacts_dev; use super::*; use crate::build::try_install_plonk_bn254_artifacts; use anyhow::Result; + use build::try_build_plonk_bn254_artifacts_dev; use p3_field::PrimeField32; use serial_test::serial; use sphinx_core::io::SphinxStdin; @@ -726,7 +699,8 @@ mod tests { let elf = include_bytes!("../../tests/fibonacci/elf/riscv32im-succinct-zkvm-elf"); tracing::info!("initializing prover"); - let prover = SphinxProver::new(); + let mut prover = SphinxProver::new(); + prover.core_opts.shard_size = 1 << 12; tracing::info!("setup elf"); let (pk, vk) = prover.setup(elf); @@ -756,11 +730,11 @@ mod tests { let bytes = bincode::serialize(&wrapped_bn254_proof).unwrap(); // Save the proof. - let mut file = File::create("proof-with-pis.json").unwrap(); + let mut file = File::create("proof-with-pis.bin").unwrap(); file.write_all(bytes.as_slice()).unwrap(); // Load the proof. - let mut file = File::open("proof-with-pis.json").unwrap(); + let mut file = File::open("proof-with-pis.bin").unwrap(); let mut bytes = Vec::new(); file.read_to_end(&mut bytes).unwrap(); diff --git a/prover/src/verify.rs b/prover/src/verify.rs index f62dabde0..5a9983c92 100644 --- a/prover/src/verify.rs +++ b/prover/src/verify.rs @@ -8,6 +8,7 @@ use sphinx_core::air::MachineAir; use sphinx_core::{ air::PublicValues, io::SphinxPublicValues, + runtime::subproof::SubproofVerifier, stark::{MachineProof, MachineVerificationError, StarkGenericConfig}, utils::BabyBearPoseidon2, }; @@ -112,11 +113,6 @@ impl SphinxProver { .core_machine .shard_chips_ordered(&shard_proof.chip_ordering) .collect::>(); - let program_memory_init_count = chips - .clone() - .into_iter() - .filter(|chip| chip.as_ref().name() == "MemoryProgram") - .count(); let memory_init_count = chips .clone() .into_iter() @@ -127,27 +123,14 @@ impl SphinxProver { .filter(|chip| chip.as_ref().name() == "MemoryFinalize") .count(); - // Assert that the `MemoryProgram` chip only exists in the first shard. - if i == 0 && program_memory_init_count != 1 { - return Err(MachineVerificationError::InvalidChipOccurence( - "memory should exist in the first chip".to_string(), - )); - } - // TODO(wwared): Uncomment after upcoming ports update verifiers, see issue #38 - // if i != 0 && program_memory_init_count > 0 { - // return Err(MachineVerificationError::InvalidChipOccurence( - // "memory program should not exist in the first chip".to_string(), - // )); - // } - // Assert that the `MemoryInit` and `MemoryFinalize` chips only exist in the last shard. - if i != proof.0.len() - 1 && (memory_final_count > 0 || memory_init_count > 0) { + if i != 0 && (memory_final_count > 0 || memory_init_count > 0) { return Err(MachineVerificationError::InvalidChipOccurence( "memory init and finalize should not eixst anywhere but the last chip" .to_string(), )); } - if i == proof.0.len() - 1 && (memory_init_count != 1 || memory_final_count != 1) { + if i == 0 && (memory_init_count != 1 || memory_final_count != 1) { return Err(MachineVerificationError::InvalidChipOccurence( "memory init and finalize should exist the last chip".to_string(), )); @@ -313,3 +296,37 @@ pub fn verify_plonk_bn254_public_inputs( Ok(()) } + +impl SubproofVerifier for &SphinxProver { + fn verify_deferred_proof( + &self, + proof: &sphinx_core::stark::ShardProof, + vk: &sphinx_core::stark::StarkVerifyingKey, + vk_hash: [u32; 8], + committed_value_digest: [u32; 8], + ) -> Result<(), MachineVerificationError> { + // Check that the vk hash matches the vk hash from the input. + if vk.hash_u32() != vk_hash { + return Err(MachineVerificationError::InvalidPublicValues( + "vk hash from syscall does not match vkey from input", + )); + } + // Check that proof is valid. + self.verify_compressed( + &SphinxReduceProof { + proof: proof.clone(), + }, + &SphinxVerifyingKey { vk: vk.clone() }, + )?; + // Check that the committed value digest matches the one from syscall + let public_values: &RecursionPublicValues<_> = proof.public_values.as_slice().borrow(); + for (i, word) in public_values.committed_value_digest.iter().enumerate() { + if *word != committed_value_digest[i].into() { + return Err(MachineVerificationError::InvalidPublicValues( + "committed_value_digest does not match", + )); + } + } + Ok(()) + } +} diff --git a/recursion/compiler/src/asm/compiler.rs b/recursion/compiler/src/asm/compiler.rs index dd0231dce..c0573d320 100644 --- a/recursion/compiler/src/asm/compiler.rs +++ b/recursion/compiler/src/asm/compiler.rs @@ -533,6 +533,12 @@ impl + TwoAdicField> AsmCo DslIr::Halt => { self.push(AsmInstruction::Halt, trace); } + DslIr::ExpReverseBitsLen(base, ptr, len) => { + self.push( + AsmInstruction::ExpReverseBitsLen(base.fp(), ptr.fp(), len.fp()), + trace, + ); + } _ => unimplemented!(), } } @@ -591,7 +597,7 @@ impl + TwoAdicField> AsmCo pub fn compile(self) -> RecursionProgram { let code = self.code(); - tracing::info!("recursion program size: {}", code.size()); + tracing::debug!("recursion program size: {}", code.size()); code.machine_code() } diff --git a/recursion/compiler/src/asm/instruction.rs b/recursion/compiler/src/asm/instruction.rs index a570fc277..e90301536 100644 --- a/recursion/compiler/src/asm/instruction.rs +++ b/recursion/compiler/src/asm/instruction.rs @@ -166,18 +166,24 @@ pub enum AsmInstruction { /// Hint a vector of blocks. Hint(i32), - // FRIFold(m, input). + /// FRIFold(m, input). FriFold(i32, i32), - // Commit(val, index). + /// Commit(val, index). Commit(i32, i32), - // RegisterPublicValue(val). + /// RegisterPublicValue(val). RegisterPublicValue(i32), LessThan(i32, i32, i32), CycleTracker(String), + + /// ExpReverseBitsLen instruction: (mathematical description) given `x`, `exp`, `len`, bit-reverse the last `len` bits of + /// `exp` and raise `x` to the power of the resulting value. The arguments are a pointer to the + /// addresss at which `x` is located (will be written to with the result), a pointer to the + /// address containing the bits of `exp` stored as a little-endian bit array, and `len`. + ExpReverseBitsLen(i32, i32, i32), } impl> AsmInstruction { @@ -851,6 +857,17 @@ impl> AsmInstruction { true, "".to_string(), ), + AsmInstruction::ExpReverseBitsLen(base, ptr, len) => Instruction::new( + Opcode::ExpReverseBitsLen, + i32_f(base), + i32_f_arr(ptr), + i32_f_arr(len), + F::zero(), + F::zero(), + false, + false, + "".to_string(), + ), } } @@ -1125,6 +1142,13 @@ impl> AsmInstruction { AsmInstruction::CycleTracker(name) => { write!(f, "cycle-tracker {}", name) } + AsmInstruction::ExpReverseBitsLen(base, ptr, len) => { + write!( + f, + "exp_reverse_bits_len ({})fp, ({})fp, ({})fp", + base, ptr, len + ) + } } } } diff --git a/recursion/compiler/src/ir/instructions.rs b/recursion/compiler/src/ir/instructions.rs index c71bba71e..3d143d973 100644 --- a/recursion/compiler/src/ir/instructions.rs +++ b/recursion/compiler/src/ir/instructions.rs @@ -278,4 +278,7 @@ pub enum DslIr { LessThan(Var, Var, Var), /// Tracks the number of cycles used by a block of code annotated by the string input. CycleTracker(String), + + // Reverse bits exponentiation. + ExpReverseBitsLen(Ptr, Var, Var), } diff --git a/recursion/compiler/src/ir/utils.rs b/recursion/compiler/src/ir/utils.rs index cd292b168..ecff47ef4 100644 --- a/recursion/compiler/src/ir/utils.rs +++ b/recursion/compiler/src/ir/utils.rs @@ -133,6 +133,41 @@ impl Builder { result } + /// A version of `exp_reverse_bits_len` that uses the ExpReverseBitsLen precompile. + pub fn exp_reverse_bits_len_fast( + &mut self, + x: Felt, + power_bits: &Array>, + bit_len: impl Into>, + ) -> Felt { + // Instantiate an array of length one and store the value of x. + let mut x_copy_arr: Array> = self.dyn_array(1); + self.set(&mut x_copy_arr, 0, x); + // Get a pointer to the address holding x. + let x_copy_arr_ptr = match x_copy_arr { + Array::Dyn(ptr, _) => ptr, + _ => panic!("Expected a dynamic array"), + }; + + // Materialize the bit length as a Var. + let bit_len_var = bit_len.into().materialize(self); + // Get a pointer to the array of bits in the exponent. + let ptr = match power_bits { + Array::Dyn(ptr, _) => ptr, + _ => panic!("Expected a dynamic array"), + }; + + // Call the DslIR instruction ExpReverseBitsLen, which modifies the memory pointed to by `x_copy_arr_ptr`. + self.push(DslIr::ExpReverseBitsLen( + x_copy_arr_ptr, + ptr.address, + bit_len_var, + )); + + // Return the value stored at the address pointed to by `x_copy_arr_ptr`. + self.get(&x_copy_arr, 0) + } + /// Exponentiates a variable to a list of bits in little endian. pub fn exp_power_of_2_v( &mut self, diff --git a/recursion/core/Cargo.toml b/recursion/core/Cargo.toml index 73b654955..9babe3735 100644 --- a/recursion/core/Cargo.toml +++ b/recursion/core/Cargo.toml @@ -13,6 +13,7 @@ p3-matrix = { workspace = true } p3-maybe-rayon = { workspace = true, features = ["parallel"] } p3-poseidon2 = { workspace = true } p3-symmetric = { workspace = true } +p3-util = { workspace = true } sphinx-derive = { path = "../../derive" } sphinx-primitives = { path = "../../primitives" } tracing = { workspace = true } diff --git a/recursion/core/src/air/is_zero.rs b/recursion/core/src/air/is_zero.rs new file mode 100644 index 000000000..75c8cc912 --- /dev/null +++ b/recursion/core/src/air/is_zero.rs @@ -0,0 +1,82 @@ +//! An operation to check if the input is 0. +//! +//! This is guaranteed to return 1 if and only if the input is 0. +//! +//! The idea is that 1 - input * inverse is exactly the boolean value indicating whether the input +//! is 0. +use p3_air::AirBuilder; +use p3_field::AbstractField; +use p3_field::Field; +use sphinx_core::air::BaseAirBuilder; +use sphinx_derive::AlignedBorrow; + +/// A set of columns needed to compute whether the given word is 0. +#[derive(AlignedBorrow, Default, Debug, Clone, Copy)] +#[repr(C)] +pub struct IsZeroOperation { + /// The inverse of the input. + pub inverse: T, + + /// Result indicating whether the input is 0. This equals `inverse * input == 0`. + pub result: T, +} + +impl IsZeroOperation { + pub fn populate(&mut self, a: F) -> F { + let (inverse, result) = if a.is_zero() { + (F::zero(), F::one()) + } else { + (a.inverse(), F::zero()) + }; + + self.inverse = inverse; + self.result = result; + + let prod = inverse * a; + debug_assert!(prod == F::one() || prod.is_zero()); + + result + } +} + +impl IsZeroOperation { + pub fn eval( + builder: &mut AB, + a: &AB::Expr, + cols: IsZeroOperation, + is_real: &AB::Expr, + ) { + // Assert that the `is_real` is a boolean. + builder.assert_bool(is_real.clone()); + // Assert that the result is boolean. + builder.when(is_real.clone()).assert_bool(cols.result); + + // 1. Input == 0 => is_zero = 1 regardless of the inverse. + // 2. Input != 0 + // 2.1. inverse is correctly set => is_zero = 0. + // 2.2. inverse is incorrect + // 2.2.1 inverse is nonzero => is_zero isn't bool, it fails. + // 2.2.2 inverse is 0 => is_zero is 1. But then we would assert that a = 0. And that + // assert fails. + + // If the input is 0, then any product involving it is 0. If it is nonzero and its inverse + // is correctly set, then the product is 1. + + let one = AB::Expr::one(); + let inverse = cols.inverse; + + let is_zero = one.clone() - inverse * a.clone(); + + builder + .when(is_real.clone()) + .assert_eq(is_zero, cols.result); + + builder.when(is_real.clone()).assert_bool(cols.result); + + // If the result is 1, then the input is 0. + builder + .when(is_real.clone()) + .when(cols.result) + .assert_zero(a.clone()); + } +} diff --git a/recursion/core/src/air/mod.rs b/recursion/core/src/air/mod.rs index 9e118c655..6fb045117 100644 --- a/recursion/core/src/air/mod.rs +++ b/recursion/core/src/air/mod.rs @@ -2,6 +2,7 @@ mod block; mod builder; mod extension; mod is_ext_zero; +mod is_zero; mod multi_builder; mod public_values; @@ -9,5 +10,6 @@ pub use block::*; pub use builder::*; pub use extension::*; pub use is_ext_zero::*; +pub use is_zero::*; pub use multi_builder::*; pub use public_values::*; diff --git a/recursion/core/src/cpu/air/mod.rs b/recursion/core/src/cpu/air/mod.rs index f80eb9822..91dc7b5a5 100644 --- a/recursion/core/src/cpu/air/mod.rs +++ b/recursion/core/src/cpu/air/mod.rs @@ -72,7 +72,10 @@ where } // Constrain the syscalls. - let send_syscall = local.selectors.is_poseidon + local.selectors.is_fri_fold; + let send_syscall = local.selectors.is_poseidon + + local.selectors.is_fri_fold + + local.selectors.is_exp_reverse_bits_len; + let operands = [ local.clk.into(), local.a.value()[0].into(), @@ -118,7 +121,7 @@ impl CpuChip { builder .when_transition() .when(next.is_real) - .when_not(local.selectors.is_fri_fold) + .when_not(local.selectors.is_fri_fold + local.selectors.is_exp_reverse_bits_len) .assert_eq(local.clk.into() + AB::F::from_canonical_u32(4), next.clk); builder @@ -126,6 +129,12 @@ impl CpuChip { .when(next.is_real) .when(local.selectors.is_fri_fold) .assert_eq(local.clk.into() + local.a.value()[0], next.clk); + + builder + .when_transition() + .when(next.is_real) + .when(local.selectors.is_exp_reverse_bits_len) + .assert_eq(local.clk.into() + local.c.value()[0], next.clk); } /// Eval the is_real flag. diff --git a/recursion/core/src/cpu/columns/opcode.rs b/recursion/core/src/cpu/columns/opcode.rs index 020be218a..2254e3672 100644 --- a/recursion/core/src/cpu/columns/opcode.rs +++ b/recursion/core/src/cpu/columns/opcode.rs @@ -1,3 +1,4 @@ +use core::mem::size_of; use p3_field::PrimeField32; use sphinx_derive::AlignedBorrow; @@ -6,7 +7,7 @@ use crate::{ runtime::{instruction_is_heap_expand, Opcode}, }; -const OPCODE_COUNT: usize = core::mem::size_of::>(); +const OPCODE_COUNT: usize = size_of::>(); /// Selectors for the opcode. /// @@ -44,7 +45,7 @@ pub struct OpcodeSelectorCols { pub is_fri_fold: T, pub is_commit: T, pub is_ext_to_felt: T, - + pub is_exp_reverse_bits_len: T, pub is_heap_expand: T, } @@ -70,6 +71,7 @@ impl OpcodeSelectorCols { Opcode::TRAP => self.is_trap = F::one(), Opcode::HALT => self.is_halt = F::one(), Opcode::FRIFold => self.is_fri_fold = F::one(), + Opcode::ExpReverseBitsLen => self.is_exp_reverse_bits_len = F::one(), Opcode::Poseidon2Compress => self.is_poseidon = F::one(), Opcode::Commit => self.is_commit = F::one(), Opcode::HintExt2Felt => self.is_ext_to_felt = F::one(), @@ -125,6 +127,7 @@ impl IntoIterator for &OpcodeSelectorCols { self.is_fri_fold, self.is_commit, self.is_ext_to_felt, + self.is_exp_reverse_bits_len, self.is_heap_expand, ] .into_iter() diff --git a/recursion/core/src/exp_reverse_bits/mod.rs b/recursion/core/src/exp_reverse_bits/mod.rs new file mode 100644 index 000000000..b1be0a9c0 --- /dev/null +++ b/recursion/core/src/exp_reverse_bits/mod.rs @@ -0,0 +1,529 @@ +#![allow(clippy::needless_range_loop)] + +use crate::air::{Block, IsZeroOperation, RecursionMemoryAirBuilder}; +use crate::memory::{MemoryReadSingleCols, MemoryReadWriteSingleCols}; +use crate::runtime::Opcode; +use core::borrow::Borrow; +use core::mem::size_of; +use itertools::Itertools; +use p3_air::{Air, AirBuilder, BaseAir}; +use p3_field::PrimeField32; +use p3_field::{AbstractField, Field}; +use p3_matrix::dense::RowMajorMatrix; +use p3_matrix::Matrix; +use p3_util::reverse_bits_len; +use sphinx_core::air::{ + BaseAirBuilder, EventLens, ExtensionAirBuilder, MachineAir, SphinxAirBuilder, WithEvents, +}; +use sphinx_core::utils::pad_rows_fixed; +use sphinx_derive::AlignedBorrow; +use std::borrow::BorrowMut; +use std::marker::PhantomData; +use tracing::instrument; + +use crate::air::SphinxRecursionAirBuilder; +use crate::memory::MemoryRecord; +use crate::runtime::{ExecutionRecord, RecursionProgram}; + +pub const NUM_EXP_REVERSE_BITS_LEN_COLS: usize = size_of::>(); + +#[derive(Default)] +pub struct ExpReverseBitsLenChip { + pub fixed_log2_rows: Option, + pub pad: bool, + pub _phantom: PhantomData, +} + +#[derive(Debug, Clone)] +pub struct ExpReverseBitsLenEvent { + /// The clk cycle for the event. + pub clk: F, + + /// Memory records to keep track of the value stored in the x parameter, and the current bit + /// of the exponent being scanned. + pub x: MemoryRecord, + pub current_bit: MemoryRecord, + + /// The length parameter of the function. + pub len: F, + + /// The previous accumulator value, needed to compute the current accumulator value. + pub prev_accum: F, + + /// The current accumulator value. + pub accum: F, + + /// A pointer to the memory address storing the exponent. + pub ptr: F, + + /// A pointer to the memory address storing the base. + pub base_ptr: F, + + /// Which step (in the range 0..len) of the computation we are in. + pub iteration_num: F, +} + +impl ExpReverseBitsLenEvent { + /// A way to construct a list of dummy events from input x and clk, used for testing. + pub fn dummy_from_input(x: F, exponent: u32, len: F, timestamp: F) -> Vec { + let mut events = Vec::new(); + let mut new_len = len; + let mut new_exponent = exponent; + let mut accum = F::one(); + + for i in 0..len.as_canonical_u32() { + let current_bit = new_exponent % 2; + let prev_accum = accum; + accum = prev_accum * prev_accum * if current_bit == 0 { F::one() } else { x }; + events.push(Self { + clk: timestamp + F::from_canonical_u32(i), + x: MemoryRecord::new_write( + F::one(), + Block::from([ + if i == len.as_canonical_u32() - 1 { + accum + } else { + x + }, + F::zero(), + F::zero(), + F::zero(), + ]), + timestamp + F::from_canonical_u32(i), + Block::from([x, F::zero(), F::zero(), F::zero()]), + timestamp + F::from_canonical_u32(i) - F::one(), + ), + current_bit: MemoryRecord::new_read( + F::zero(), + Block::from([ + F::from_canonical_u32(current_bit), + F::zero(), + F::zero(), + F::zero(), + ]), + timestamp + F::from_canonical_u32(i), + timestamp + F::from_canonical_u32(i) - F::one(), + ), + len: new_len, + prev_accum, + accum, + ptr: F::zero(), + base_ptr: F::one(), + iteration_num: F::from_canonical_u32(i), + }); + new_exponent /= 2; + new_len -= F::one(); + } + assert_eq!( + accum, + x.exp_u64(reverse_bits_len(exponent as usize, len.as_canonical_u32() as usize) as u64) + ); + events + } +} + +#[derive(AlignedBorrow, Debug, Clone, Copy)] +#[repr(C)] +pub struct ExpReverseBitsLenCols { + pub clk: T, + + /// The base of the exponentiation. + pub x: MemoryReadWriteSingleCols, + + /// The length parameter of the exponentiation. This is decremented by 1 every iteration. + pub len: T, + + /// The current bit of the exponent. This is read from memory. + pub current_bit: MemoryReadSingleCols, + + /// The previous accumulator squared. + pub prev_accum_squared: T, + + /// The accumulator of the current iteration. + pub accum: T, + + /// A flag column to check whether the current row represents the last iteration of the computation. + pub is_last: IsZeroOperation, + + /// A flag column to check whether the current row represents the first iteration of the computation. + pub is_first: IsZeroOperation, + + /// A column to count up from 0 to the length of the exponent. + pub iteration_num: T, + + /// A column which equals x if `current_bit` is on, and 1 otherwise. + pub multiplier: T, + + /// The memory address storing the exponent. + pub ptr: T, + + /// The memory address storing the base. + pub base_ptr: T, + + /// A flag column to check whether the base_ptr memory is accessed. Is equal to `is_first` OR + /// `is_last`. + pub x_mem_access_flag: T, + + pub is_real: T, +} + +impl BaseAir for ExpReverseBitsLenChip { + fn width(&self) -> usize { + NUM_EXP_REVERSE_BITS_LEN_COLS + } +} + +impl<'a, F: Field, const DEGREE: usize> WithEvents<'a> for ExpReverseBitsLenChip { + type Events = &'a [ExpReverseBitsLenEvent]; +} + +impl MachineAir for ExpReverseBitsLenChip { + type Record = ExecutionRecord; + + type Program = RecursionProgram; + + fn name(&self) -> String { + "ExpReverseBitsLen".to_string() + } + + fn generate_dependencies>(&self, _: &EL, _: &mut Self::Record) { + // This is a no-op. + } + + #[instrument(name = "generate exp reverse bits len trace", level = "debug", skip_all, fields(rows = input.events().len()))] + fn generate_trace>( + &self, + input: &EL, + _: &mut ExecutionRecord, + ) -> RowMajorMatrix { + let mut rows = input + .events() + .iter() + .map(|event| { + let mut row = [F::zero(); NUM_EXP_REVERSE_BITS_LEN_COLS]; + + let cols: &mut ExpReverseBitsLenCols = row.as_mut_slice().borrow_mut(); + + cols.clk = event.clk; + + cols.x.populate(&event.x); + cols.current_bit.populate(&event.current_bit); + cols.len = event.len; + cols.accum = event.accum; + cols.prev_accum_squared = event.prev_accum * event.prev_accum; + cols.is_last.populate(F::one() - event.len); + cols.is_first.populate(event.iteration_num); + cols.is_real = F::one(); + cols.iteration_num = event.iteration_num; + cols.multiplier = if event.current_bit.value + == Block([F::one(), F::zero(), F::zero(), F::zero()]) + { + // The event may change the value stored in the x memory access, and we need to + // use the previous value. + event.x.prev_value[0] + } else { + F::one() + }; + cols.ptr = event.ptr; + cols.base_ptr = event.base_ptr; + cols.x_mem_access_flag = + F::from_bool(cols.len == F::one() || cols.iteration_num == F::zero()); + + row + }) + .collect_vec(); + + // Pad the trace to a power of two. + if self.pad { + pad_rows_fixed( + &mut rows, + || [F::zero(); NUM_EXP_REVERSE_BITS_LEN_COLS], + self.fixed_log2_rows, + ); + } + + // Convert the trace to a row major matrix. + let trace = RowMajorMatrix::new( + rows.into_iter().flatten().collect(), + NUM_EXP_REVERSE_BITS_LEN_COLS, + ); + + #[cfg(debug_assertions)] + println!( + "exp reverse bits len trace dims is width: {:?}, height: {:?}", + trace.width(), + trace.height() + ); + + trace + } + + fn included(&self, record: &Self::Record) -> bool { + !record.exp_reverse_bits_len_events.is_empty() + } +} + +impl ExpReverseBitsLenChip { + pub fn eval_exp_reverse_bits_len< + AB: BaseAirBuilder + ExtensionAirBuilder + RecursionMemoryAirBuilder + SphinxAirBuilder, + >( + &self, + builder: &mut AB, + local: &ExpReverseBitsLenCols, + next: &ExpReverseBitsLenCols, + memory_access: AB::Var, + ) { + // Dummy constraints to normalize to DEGREE when DEGREE > 3. + if DEGREE > 3 { + let lhs = (0..DEGREE) + .map(|_| local.is_real.into()) + .product::(); + let rhs = (0..DEGREE) + .map(|_| local.is_real.into()) + .product::(); + builder.assert_eq(lhs, rhs); + } + + // Constraint that the operands are sent from the CPU table. + let operands = [ + local.clk.into(), + local.base_ptr.into(), + local.ptr.into(), + local.len.into(), + ]; + builder.receive_table( + Opcode::ExpReverseBitsLen.as_field::(), + &operands, + local.is_first.result, + ); + + IsZeroOperation::::eval( + builder, + &(AB::Expr::one() - local.len), + local.is_last, + &local.is_real.into(), + ); + // Assert that the boolean columns are boolean. + builder.assert_bool(local.is_real); + + let current_bit_val = local.current_bit.access.value; + + // Probably redundant, but we assert here that the current bit value is boolean. + builder.assert_bool(current_bit_val); + + // Assert that `is_first` is on for the first row. + builder.when_first_row().assert_one(local.is_first.result); + + // Assert that the next row after a row for which `is_last` is on has `is_first` on. + builder + .when_transition() + .when(next.is_real * local.is_last.result) + .assert_one(next.is_first.result); + + // The accumulator needs to start with the multiplier for every `is_first` row. + builder + .when(local.is_first.result) + .assert_eq(local.accum, local.multiplier); + + // Assert that the last real row has `is_last` on. + builder + .when(local.is_real * (AB::Expr::one() - next.is_real)) + .assert_one(local.is_last.result); + + // `multiplier` is x if the current bit is 1, and 1 if the current bit is 0. + builder + .when(current_bit_val) + .assert_eq(local.multiplier, local.x.prev_value); + builder + .when(local.is_real) + .when_not(current_bit_val) + .assert_eq(local.multiplier, AB::Expr::one()); + + // To get `next.accum`, we multiply `local.prev_accum_squared` by `local.multiplier` when not + // `is_last`. + builder + .when_transition() + .when_not(local.is_last.result) + .assert_eq(local.accum, local.prev_accum_squared * local.multiplier); + + // Constrain the accum_squared column. + builder + .when_transition() + .when_not(local.is_last.result) + .assert_eq(next.prev_accum_squared, local.accum * local.accum); + + // Constrain the memory address `base_ptr` to be the same as the next, as long as not `is_last`. + builder + .when_transition() + .when_not(local.is_last.result) + .assert_eq(local.base_ptr, next.base_ptr); + + // The `len` counter must decrement when not `is_last`. + builder + .when_transition() + .when(local.is_real) + .when_not(local.is_last.result) + .assert_eq(local.len, next.len + AB::Expr::one()); + + // The `iteration_num` counter must increment when not `is_last`. + builder + .when_transition() + .when(local.is_real) + .when_not(local.is_last.result) + .assert_eq(local.iteration_num + AB::Expr::one(), next.iteration_num); + + // The `iteration_num` counter must be 0 iff `is_first` is on. + builder + .when(local.is_first.result) + .assert_eq(local.iteration_num, AB::Expr::zero()); + + // Access the memory for current_bit. + builder.recursion_eval_memory_access_single( + local.clk, + local.ptr, + &local.current_bit, + memory_access, + ); + + // Constrain that the x_mem_access_flag is true when `is_first` or `is_last`. + builder.when(local.is_real).assert_eq( + local.x_mem_access_flag, + local.is_first.result + local.is_last.result + - local.is_first.result * local.is_last.result, + ); + + // Access the memory for x. + // This only needs to be done for the first and last iterations. + builder.recursion_eval_memory_access_single( + local.clk, + local.base_ptr, + &local.x, + local.x_mem_access_flag, + ); + + // The `base_ptr` column stays the same when not `is_last`. + builder + .when_transition() + .when(next.is_real) + .when_not(local.is_last.result) + .assert_eq(next.base_ptr, local.base_ptr); + + // Ensure sequential `clk` values. + builder + .when_transition() + .when_not(local.is_last.result) + .when(next.is_real) + .assert_eq(local.clk + AB::Expr::one(), next.clk); + + // Ensure that the value at the x memory access is unchanged when not `is_last`. + builder + .when_not(local.is_last.result) + .assert_eq(local.x.access.value, local.x.prev_value); + + // Ensure that the value at the x memory access is `accum` when `is_last`. + builder + .when(local.is_last.result) + .assert_eq(local.accum, local.x.access.value); + } + + pub const fn do_exp_bit_memory_access(local: &ExpReverseBitsLenCols) -> T { + local.is_real + } +} + +impl Air for ExpReverseBitsLenChip +where + AB: SphinxRecursionAirBuilder, +{ + fn eval(&self, builder: &mut AB) { + let main = builder.main(); + let (local, next) = (main.row_slice(0), main.row_slice(1)); + let local: &ExpReverseBitsLenCols = (*local).borrow(); + let next: &ExpReverseBitsLenCols = (*next).borrow(); + self.eval_exp_reverse_bits_len::( + builder, + local, + next, + Self::do_exp_bit_memory_access::(local), + ); + } +} + +#[cfg(test)] +mod tests { + use itertools::Itertools; + use std::marker::PhantomData; + use std::time::Instant; + + use p3_baby_bear::BabyBear; + use p3_baby_bear::DiffusionMatrixBabyBear; + use p3_field::AbstractField; + use p3_matrix::{dense::RowMajorMatrix, Matrix}; + use p3_poseidon2::Poseidon2; + use p3_poseidon2::Poseidon2ExternalMatrixGeneral; + use sphinx_core::stark::StarkGenericConfig; + use sphinx_core::{ + air::MachineAir, + utils::{uni_stark_prove, uni_stark_verify, BabyBearPoseidon2}, + }; + + use crate::exp_reverse_bits::ExpReverseBitsLenChip; + use crate::exp_reverse_bits::ExpReverseBitsLenEvent; + use crate::runtime::ExecutionRecord; + + #[test] + fn prove_babybear() { + let config = BabyBearPoseidon2::compressed(); + let mut challenger = config.challenger(); + + let chip = ExpReverseBitsLenChip::<_, 5> { + pad: true, + fixed_log2_rows: None, + _phantom: PhantomData, + }; + + let test_xs = (1..16).map(BabyBear::from_canonical_u32).collect_vec(); + + let test_exponents = (1..16).collect_vec(); + + let mut input_exec = ExecutionRecord::::default(); + for (x, exponent) in test_xs.into_iter().zip_eq(test_exponents) { + let mut events = ExpReverseBitsLenEvent::dummy_from_input( + x, + exponent, + BabyBear::from_canonical_u32(exponent.ilog2() + 1), + x, + ); + input_exec.exp_reverse_bits_len_events.append(&mut events); + } + println!( + "input exec: {:?}", + input_exec.exp_reverse_bits_len_events.len() + ); + let trace: RowMajorMatrix = + chip.generate_trace(&input_exec, &mut ExecutionRecord::::default()); + println!( + "trace dims is width: {:?}, height: {:?}", + trace.width(), + trace.height() + ); + + let start = Instant::now(); + let proof = uni_stark_prove(&config, &chip, &mut challenger, trace); + let duration = start.elapsed().as_secs_f64(); + println!("proof duration = {:?}", duration); + + let mut challenger: p3_challenger::DuplexChallenger< + BabyBear, + Poseidon2, + 16, + 8, + > = config.challenger(); + let start = Instant::now(); + uni_stark_verify(&config, &chip, &mut challenger, &proof) + .expect("expected proof to be valid"); + + let duration = start.elapsed().as_secs_f64(); + println!("verify duration = {:?}", duration); + } +} diff --git a/recursion/core/src/fri_fold/mod.rs b/recursion/core/src/fri_fold/mod.rs index 411e219aa..8d41ee5a7 100644 --- a/recursion/core/src/fri_fold/mod.rs +++ b/recursion/core/src/fri_fold/mod.rs @@ -2,6 +2,7 @@ use crate::air::RecursionMemoryAirBuilder; use crate::memory::{MemoryReadCols, MemoryReadSingleCols, MemoryReadWriteCols}; use crate::runtime::Opcode; use core::borrow::Borrow; +use core::mem::size_of; use itertools::Itertools; use p3_air::{Air, AirBuilder, BaseAir}; use p3_field::PrimeField32; @@ -21,12 +22,13 @@ use crate::air::SphinxRecursionAirBuilder; use crate::memory::MemoryRecord; use crate::runtime::{ExecutionRecord, RecursionProgram}; -pub const NUM_FRI_FOLD_COLS: usize = core::mem::size_of::>(); +pub const NUM_FRI_FOLD_COLS: usize = size_of::>(); #[derive(Default)] pub struct FriFoldChip { pub fixed_log2_rows: Option, pub _phantom: PhantomData, + pub pad: bool, } #[derive(Debug, Clone)] @@ -149,11 +151,13 @@ impl MachineAir for FriFoldChip FriFoldChip { .when(next.is_real) .assert_zero(next.m); - // Ensure that all rows for a FRI FOLD invocation have the same input_ptr, clk, and sequential m values. + // Ensure that all rows for a FRI FOLD invocation have the same input_ptr and sequential clk and m values. builder .when_transition() .when_not(local.is_last_iteration) diff --git a/recursion/core/src/lib.rs b/recursion/core/src/lib.rs index db37f40f6..785179fa7 100644 --- a/recursion/core/src/lib.rs +++ b/recursion/core/src/lib.rs @@ -1,5 +1,6 @@ pub mod air; pub mod cpu; +pub mod exp_reverse_bits; pub mod fri_fold; pub mod memory; pub mod multi; diff --git a/recursion/core/src/multi/mod.rs b/recursion/core/src/multi/mod.rs index cced5eb36..45025e244 100644 --- a/recursion/core/src/multi/mod.rs +++ b/recursion/core/src/multi/mod.rs @@ -1,6 +1,7 @@ use std::borrow::{Borrow, BorrowMut}; use std::marker::PhantomData; +use core::mem::size_of; use itertools::Itertools; use p3_air::{Air, AirBuilder, BaseAir}; use p3_field::{Field, PrimeField32}; @@ -15,7 +16,7 @@ use crate::fri_fold::{FriFoldChip, FriFoldCols}; use crate::poseidon2::{Poseidon2Chip, Poseidon2Cols}; use crate::runtime::{ExecutionRecord, RecursionProgram}; -pub const NUM_MULTI_COLS: usize = core::mem::size_of::>(); +pub const NUM_MULTI_COLS: usize = size_of::>(); #[derive(Default)] pub struct MultiChip { @@ -173,14 +174,12 @@ where // all the fri fold rows are first, then the posiedon2 rows, and finally any padded (non-real) rows. // First verify that all real rows are contiguous. - builder.when_first_row().assert_one(local_is_real.clone()); builder .when_transition() .when_not(local_is_real.clone()) .assert_zero(next_is_real.clone()); // Next, verify that all fri fold rows are before the poseidon2 rows within the real rows section. - builder.when_first_row().assert_one(local.is_fri_fold); builder .when_transition() .when(next_is_real) diff --git a/recursion/core/src/poseidon2/external.rs b/recursion/core/src/poseidon2/external.rs index 3db722f0d..c7614b66d 100644 --- a/recursion/core/src/poseidon2/external.rs +++ b/recursion/core/src/poseidon2/external.rs @@ -25,7 +25,8 @@ pub(crate) const WIDTH: usize = 16; #[derive(Default)] pub struct Poseidon2Chip { pub fixed_log2_rows: Option, - _phantom: PhantomData, + pub _phantom: PhantomData, + pub pad: bool, } impl BaseAir for Poseidon2Chip { @@ -67,7 +68,7 @@ impl Poseidon2Chip { .sum::(); let is_memory_write = local.rounds[local.rounds.len() - 1]; - self.eval_control_flow_and_inputs::(builder, local, next); + self.eval_control_flow_and_inputs(builder, local, next); self.eval_syscall(builder, local, receive_table); @@ -449,6 +450,7 @@ mod tests { let chip = Poseidon2Chip { fixed_log2_rows: None, _phantom: PhantomData, + pad: true, }; let rng = &mut rand::thread_rng(); @@ -499,6 +501,7 @@ mod tests { let chip = Poseidon2Chip { fixed_log2_rows: None, _phantom: PhantomData, + pad: true, }; let trace: RowMajorMatrix = chip.generate_trace(&input_exec, &mut ExecutionRecord::::default()); diff --git a/recursion/core/src/poseidon2/trace.rs b/recursion/core/src/poseidon2/trace.rs index 7070112b9..1ae34541d 100644 --- a/recursion/core/src/poseidon2/trace.rs +++ b/recursion/core/src/poseidon2/trace.rs @@ -181,11 +181,21 @@ impl MachineAir for Poseidon2Chip { let num_real_rows = rows.len(); // Pad the trace to a power of two. - pad_rows_fixed( - &mut rows, - || [F::zero(); NUM_POSEIDON2_COLS], - self.fixed_log2_rows, - ); + if self.pad { + pad_rows_fixed( + &mut rows, + || [F::zero(); NUM_POSEIDON2_COLS], + self.fixed_log2_rows, + ); + } + + let mut round_num = 0; + for row in rows[num_real_rows..].iter_mut() { + let cols: &mut Poseidon2Cols = row.as_mut_slice().borrow_mut(); + cols.rounds[round_num] = F::one(); + + round_num = (round_num + 1) % rounds; + } let mut round_num = 0; for row in rows[num_real_rows..].iter_mut() { diff --git a/recursion/core/src/range_check/mod.rs b/recursion/core/src/range_check/mod.rs index c3fc318ec..2ae7e74fd 100644 --- a/recursion/core/src/range_check/mod.rs +++ b/recursion/core/src/range_check/mod.rs @@ -32,8 +32,8 @@ impl RangeCheckChip { /// /// This function returns a pair `(trace, map)`, where: /// - `trace` is a matrix containing all possible range check values. - /// - `map` is a map from a range check lookup to the value's corresponding row it appears in the table and - /// the index of the result in the array of multiplicities. + /// - `map` is a map from a range check lookup to the value's corresponding row it appears in the table and + /// the index of the result in the array of multiplicities. pub fn trace_and_map() -> (RowMajorMatrix, BTreeMap) { // A map from a byte lookup to its corresponding row in the table and index in the array of // multiplicities. diff --git a/recursion/core/src/range_check/trace.rs b/recursion/core/src/range_check/trace.rs index 6363c80ed..21005d212 100644 --- a/recursion/core/src/range_check/trace.rs +++ b/recursion/core/src/range_check/trace.rs @@ -1,6 +1,5 @@ -use std::borrow::BorrowMut; +use std::{borrow::BorrowMut, collections::BTreeMap}; -use hashbrown::HashMap; use p3_field::{Field, PrimeField32}; use p3_matrix::dense::RowMajorMatrix; use sphinx_core::air::{EventLens, MachineAir, WithEvents}; @@ -14,7 +13,7 @@ use crate::runtime::{ExecutionRecord, RecursionProgram}; pub const NUM_ROWS: usize = 1 << 16; impl<'a, F: Field> WithEvents<'a> for RangeCheckChip { - type Events = &'a HashMap; + type Events = &'a BTreeMap; } impl MachineAir for RangeCheckChip { diff --git a/recursion/core/src/runtime/mod.rs b/recursion/core/src/runtime/mod.rs index d3a738351..0ef62de40 100644 --- a/recursion/core/src/runtime/mod.rs +++ b/recursion/core/src/runtime/mod.rs @@ -21,6 +21,7 @@ pub use utils::*; use crate::air::{Block, RECURSION_PUBLIC_VALUES_COL_MAP, RECURSIVE_PROOF_NUM_PV_ELTS}; use crate::cpu::CpuEvent; +use crate::exp_reverse_bits::ExpReverseBitsLenEvent; use crate::fri_fold::FriFoldEvent; use crate::memory::MemoryRecord; use crate::poseidon2::Poseidon2Event; @@ -586,12 +587,11 @@ where .resize(RECURSIVE_PROOF_NUM_PV_ELTS, F::zero()); self.record.public_values[RECURSION_PUBLIC_VALUES_COL_MAP.exit_code] = F::one(); - let (a_val, b_val, c_val) = self.all_rr(&instruction); let trap_pc = self.pc.as_canonical_u32() as usize; let trace = self.program.traces[trap_pc].clone(); if let Some(mut trace) = trace { trace.resolve(); - eprintln!("TRAP encountered. Backtrace:\n{:?}", trace); + panic!("TRAP encountered. Backtrace:\n{:?}", trace); } else { for nearby_pc in (0..trap_pc).rev() { let trace = self.program.traces[nearby_pc].clone(); @@ -604,9 +604,8 @@ where exit(1); } } - eprintln!("TRAP encountered. No backtrace available"); + panic!("TRAP encountered. No backtrace available"); } - (a, b, c) = (a_val, b_val, c_val); } Opcode::HALT => { self.record @@ -820,6 +819,74 @@ where next_clk = timestamp; (a, b, c) = (a_val, b_val, c_val); } + Opcode::ExpReverseBitsLen => { + // Read the operands. + let (a_val, b_val, c_val) = self.all_rr(&instruction); + + // A pointer to the base of the exponentiation. + let base = a_val[0]; + + // A pointer to the first bit (LSB) of the exponent. + let input_ptr = b_val[0]; + + // The length parameter in bit-reverse-len. + let len = c_val[0]; + + let mut timestamp = self.clk; + + let mut accum = F::one(); + + // Read the value at the pointer `base`. + let mut x_record = self.mr(base, timestamp).0; + + // Iterate over the `len` least-significant bits of the exponent. + for m in 0..len.as_canonical_u32() { + let m = F::from_canonical_u32(m); + + // Pointer to the current bit. + let ptr = input_ptr + m; + + // Read the current bit. + let (current_bit_record, current_bit) = self.mr(ptr, timestamp); + let current_bit = current_bit.ext::().as_base_slice()[0]; + + // Extract the val in `x_record` + let current_x_val = x_record.value[0]; + + let prev_accum = accum; + accum = prev_accum + * prev_accum + * if current_bit == F::one() { + current_x_val + } else { + F::one() + }; + + // On the last iteration, write accum to the address pointed to in `base`. + if m == len - F::one() { + x_record = self.mw(base, Block::from(accum), timestamp); + }; + + // Add the event for this iteration to the `ExecutionRecord`. + self.record + .exp_reverse_bits_len_events + .push(ExpReverseBitsLenEvent { + clk: timestamp, + x: x_record, + current_bit: current_bit_record, + len: len - m, + prev_accum, + accum, + ptr, + base_ptr: base, + iteration_num: m, + }); + timestamp += F::one(); + } + + next_clk = timestamp; + (a, b, c) = (a_val, b_val, c_val); + } // For both the Commit and RegisterPublicValue opcodes, we record the public value Opcode::Commit | Opcode::RegisterPublicValue => { let (a_val, b_val, c_val) = self.all_rr(&instruction); diff --git a/recursion/core/src/runtime/opcode.rs b/recursion/core/src/runtime/opcode.rs index b72e011f8..4d49fdab3 100644 --- a/recursion/core/src/runtime/opcode.rs +++ b/recursion/core/src/runtime/opcode.rs @@ -49,6 +49,7 @@ pub enum Opcode { RegisterPublicValue = 42, LessThanF = 43, CycleTracker = 44, + ExpReverseBitsLen = 45, } impl Opcode { diff --git a/recursion/core/src/runtime/record.rs b/recursion/core/src/runtime/record.rs index 9279ad8c2..98dcf0ba1 100644 --- a/recursion/core/src/runtime/record.rs +++ b/recursion/core/src/runtime/record.rs @@ -1,4 +1,5 @@ use std::array; +use std::collections::BTreeMap; use std::sync::Arc; use hashbrown::HashMap; @@ -9,6 +10,7 @@ use sphinx_core::stark::{Indexed, MachineRecord, PROOF_MAX_NUM_PVS}; use super::RecursionProgram; use crate::air::Block; use crate::cpu::{CpuChip, CpuEvent}; +use crate::exp_reverse_bits::{ExpReverseBitsLenChip, ExpReverseBitsLenEvent}; use crate::fri_fold::{FriFoldChip, FriFoldEvent}; use crate::memory::MemoryGlobalChip; use crate::multi::MultiChip; @@ -23,8 +25,8 @@ pub struct ExecutionRecord { pub cpu_events: Vec>, pub poseidon2_events: Vec>, pub fri_fold_events: Vec>, - pub range_check_events: HashMap, - + pub range_check_events: BTreeMap, + pub exp_reverse_bits_len_events: Vec>, // (address, value) pub first_memory_record: Vec<(F, Block)>, @@ -63,6 +65,10 @@ impl MachineRecord for ExecutionRecord { "range_check_events".to_string(), self.range_check_events.len(), ); + stats.insert( + "exp_reverse_bits_len_events".to_string(), + self.exp_reverse_bits_len_events.len(), + ); stats } @@ -154,3 +160,13 @@ impl EventLens> for E ) } } + +impl EventLens> + for ExecutionRecord +{ + fn events( + &self, + ) -> as sphinx_core::air::WithEvents<'_>>::Events { + &self.exp_reverse_bits_len_events + } +} diff --git a/recursion/core/src/stark/mod.rs b/recursion/core/src/stark/mod.rs index 7d84b315c..514e7ff58 100644 --- a/recursion/core/src/stark/mod.rs +++ b/recursion/core/src/stark/mod.rs @@ -8,9 +8,9 @@ use sphinx_derive::{EventLens, MachineAir, WithEvents}; use crate::runtime::D; use crate::{ - cpu::CpuChip, fri_fold::FriFoldChip, memory::MemoryGlobalChip, multi::MultiChip, - poseidon2::Poseidon2Chip, poseidon2_wide::Poseidon2WideChip, program::ProgramChip, - range_check::RangeCheckChip, + cpu::CpuChip, exp_reverse_bits::ExpReverseBitsLenChip, fri_fold::FriFoldChip, + memory::MemoryGlobalChip, multi::MultiChip, poseidon2::Poseidon2Chip, + poseidon2_wide::Poseidon2WideChip, program::ProgramChip, range_check::RangeCheckChip, }; use core::iter::once; use std::marker::PhantomData; @@ -33,6 +33,7 @@ pub enum RecursionAir, const DEGREE: u FriFold(FriFoldChip), RangeCheck(RangeCheckChip), Multi(MultiChip), + ExpReverseBitsLen(ExpReverseBitsLenChip), } impl, const DEGREE: usize> RecursionAir { @@ -83,8 +84,16 @@ impl, const DEGREE: usize> RecursionAi .chain(once(RecursionAir::FriFold(FriFoldChip:: { fixed_log2_rows: None, _phantom: PhantomData, + pad: true, }))) .chain(once(RecursionAir::RangeCheck(RangeCheckChip::default()))) + .chain(once(RecursionAir::ExpReverseBitsLen( + ExpReverseBitsLenChip::<_, DEGREE> { + fixed_log2_rows: None, + pad: true, + _phantom: PhantomData, + }, + ))) .collect() } @@ -103,6 +112,13 @@ impl, const DEGREE: usize> RecursionAi _phantom: PhantomData, }))) .chain(once(RecursionAir::RangeCheck(RangeCheckChip::default()))) + .chain(once(RecursionAir::ExpReverseBitsLen( + ExpReverseBitsLenChip::<_, DEGREE> { + fixed_log2_rows: None, + pad: true, + _phantom: PhantomData, + }, + ))) .collect() } @@ -117,10 +133,17 @@ impl, const DEGREE: usize> RecursionAi _phantom: PhantomData, }))) .chain(once(RecursionAir::Multi(MultiChip { - fixed_log2_rows: Some(20), + fixed_log2_rows: Some(19), _phantom: PhantomData, }))) .chain(once(RecursionAir::RangeCheck(RangeCheckChip::default()))) + .chain(once(RecursionAir::ExpReverseBitsLen( + ExpReverseBitsLenChip:: { + fixed_log2_rows: None, + pad: true, + _phantom: PhantomData, + }, + ))) .collect() } } diff --git a/recursion/gnark-cli/Cargo.toml b/recursion/gnark-cli/Cargo.toml new file mode 100644 index 000000000..cd6fe2647 --- /dev/null +++ b/recursion/gnark-cli/Cargo.toml @@ -0,0 +1,10 @@ +[workspace] +[package] +name = "sp1-recursion-gnark-cli" +version = "0.1.0" +edition = "2021" + +[dependencies] +sp1-recursion-gnark-ffi = { path = "../gnark-ffi", features = ["native"] } +clap = { version = "4.3.8", features = ["derive"] } +bincode = "1.3.3" diff --git a/recursion/gnark-cli/src/main.rs b/recursion/gnark-cli/src/main.rs new file mode 100644 index 000000000..8dde4009f --- /dev/null +++ b/recursion/gnark-cli/src/main.rs @@ -0,0 +1,97 @@ +//! A simple CLI that wraps the gnark-ffi crate. This is called using Docker in gnark-ffi when the +//! native feature is disabled. + +use sphinx_recursion_gnark_ffi::ffi::{ + build_plonk_bn254, prove_plonk_bn254, test_plonk_bn254, verify_plonk_bn254, +}; + +use clap::{Args, Parser, Subcommand}; +use std::{ + fs::File, + io::{read_to_string, Write}, +}; + +#[derive(Debug, Parser)] +struct Cli { + #[command(subcommand)] + command: Command, +} + +#[allow(clippy::enum_variant_names)] +#[derive(Debug, Subcommand)] +enum Command { + BuildPlonk(BuildArgs), + ProvePlonk(ProveArgs), + VerifyPlonk(VerifyArgs), + TestPlonk(TestArgs), +} + +#[derive(Debug, Args)] +struct BuildArgs { + data_dir: String, +} + +#[derive(Debug, Args)] +struct ProveArgs { + data_dir: String, + witness_path: String, + output_path: String, +} + +#[derive(Debug, Args)] +struct VerifyArgs { + data_dir: String, + proof_path: String, + vkey_hash: String, + committed_values_digest: String, + output_path: String, +} + +#[derive(Debug, Args)] +struct TestArgs { + witness_json: String, + constraints_json: String, +} + +fn run_build(args: BuildArgs) { + build_plonk_bn254(&args.data_dir); +} + +fn run_prove(args: ProveArgs) { + let proof = prove_plonk_bn254(&args.data_dir, &args.witness_path); + let mut file = File::create(&args.output_path).unwrap(); + bincode::serialize_into(&mut file, &proof).unwrap(); +} + +fn run_verify(args: VerifyArgs) { + // For proof, we read the string from file since it can be large. + let file = File::open(&args.proof_path).unwrap(); + let proof = read_to_string(file).unwrap(); + let result = verify_plonk_bn254( + &args.data_dir, + proof.trim(), + &args.vkey_hash, + &args.committed_values_digest, + ); + let output = match result { + Ok(_) => "OK".to_string(), + Err(e) => e, + }; + let mut file = File::create(&args.output_path).unwrap(); + file.write_all(output.as_bytes()).unwrap(); +} + +fn run_test(args: TestArgs) { + test_plonk_bn254(&args.witness_json, &args.constraints_json); +} + +fn main() { + let cli = Cli::parse(); + + match cli.command { + Command::BuildPlonk(args) => run_build(args), + Command::ProvePlonk(args) => run_prove(args), + Command::VerifyPlonk(args) => run_verify(args), + Command::TestPlonk(args) => run_test(args), + } +} diff --git a/recursion/gnark-ffi/Cargo.toml b/recursion/gnark-ffi/Cargo.toml index 2cce2b0bb..c37e91acd 100644 --- a/recursion/gnark-ffi/Cargo.toml +++ b/recursion/gnark-ffi/Cargo.toml @@ -15,13 +15,19 @@ serde = { workspace = true } serde_json = { workspace = true } tempfile = { workspace = true } rand = { workspace = true } +sha2 = { workspace = true } log = { workspace = true } num-bigint = { workspace = true } cfg-if = { workspace = true } +hex = { workspace = true } +anyhow = { workspace = true } +bincode = { workspace = true } [build-dependencies] bindgen = { workspace = true } cfg-if = { workspace = true } [features] +default = ["native"] plonk = [] +native = [] diff --git a/recursion/gnark-ffi/assets/ISphinxVerifier.txt b/recursion/gnark-ffi/assets/ISphinxVerifier.txt index f9563b688..52937a160 100644 --- a/recursion/gnark-ffi/assets/ISphinxVerifier.txt +++ b/recursion/gnark-ffi/assets/ISphinxVerifier.txt @@ -1,19 +1,23 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.25; +pragma solidity ^0.8.19; /// @title Sphinx Verifier Interface +/// @author Lurk & Succinct Labs /// @notice This contract is the interface for the Sphinx Verifier. interface ISphinxVerifier { - /// @notice Returns the version of the Sphinx Verifier. + /// @notice Returns the version of Sphinx this verifier corresponds to. function VERSION() external pure returns (string memory); + /// @notice Returns the hash of the verification key. + function VKEY_HASH() external pure returns (bytes32); + /// @notice Verifies a proof with given public values and vkey. /// @param vkey The verification key for the RISC-V program. /// @param publicValues The public values encoded as bytes. - /// @param proofBytes The proof of the program execution the SP1 zkVM encoded as bytes. + /// @param proofBytes The proof of the program execution the Sphinx zkVM encoded as bytes. function verifyProof( bytes32 vkey, - bytes memory publicValues, - bytes memory proofBytes + bytes calldata publicValues, + bytes calldata proofBytes ) external view; } diff --git a/recursion/gnark-ffi/assets/SphinxMockVerifier.txt b/recursion/gnark-ffi/assets/SphinxMockVerifier.txt index ccd597dc7..e62869473 100644 --- a/recursion/gnark-ffi/assets/SphinxMockVerifier.txt +++ b/recursion/gnark-ffi/assets/SphinxMockVerifier.txt @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.25; +pragma solidity ^0.8.19; import {ISphinxVerifier} from "./ISphinxVerifier.sol"; diff --git a/recursion/gnark-ffi/assets/SphinxVerifier.txt b/recursion/gnark-ffi/assets/SphinxVerifier.txt index 685cdee16..340c9b25e 100644 --- a/recursion/gnark-ffi/assets/SphinxVerifier.txt +++ b/recursion/gnark-ffi/assets/SphinxVerifier.txt @@ -1,20 +1,27 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.25; +pragma solidity ^0.8.19; import {ISphinxVerifier} from "./ISphinxVerifier.sol"; import {PlonkVerifier} from "./PlonkVerifier.sol"; /// @title Sphinx Verifier +/// @author Lurk & Succinct Labs /// @notice This contracts implements a solidity verifier for Sphinx. contract SphinxVerifier is PlonkVerifier { + error WrongVersionProof(); + function VERSION() external pure returns (string memory) { - return "TODO"; + return "{SPHINX_CIRCUIT_VERSION}"; + } + + function VKEY_HASH() public pure returns (bytes32) { + return {VKEY_HASH}; } /// @notice Hashes the public values to a field elements inside Bn254. /// @param publicValues The public values. function hashPublicValues( - bytes memory publicValues + bytes calldata publicValues ) public pure returns (bytes32) { return sha256(publicValues) & bytes32(uint256((1 << 253) - 1)); } @@ -25,13 +32,20 @@ contract SphinxVerifier is PlonkVerifier { /// @param proofBytes The proof of the program execution the Sphinx zkVM encoded as bytes. function verifyProof( bytes32 vkey, - bytes memory publicValues, - bytes memory proofBytes + bytes calldata publicValues, + bytes calldata proofBytes ) public view { + // To ensure the proof corresponds to this verifier, we check that the first 4 bytes of + // proofBytes match the first 4 bytes of VKEY_HASH. + bytes4 proofBytesPrefix = bytes4(proofBytes[:4]); + if (proofBytesPrefix != bytes4(VKEY_HASH())) { + revert WrongVersionProof(); + } + bytes32 publicValuesDigest = hashPublicValues(publicValues); uint256[] memory inputs = new uint256[](2); inputs[0] = uint256(vkey); inputs[1] = uint256(publicValuesDigest); - this.Verify(proofBytes, inputs); + this.Verify(proofBytes[4:], inputs); } } \ No newline at end of file diff --git a/recursion/gnark-ffi/build.rs b/recursion/gnark-ffi/build.rs index 850cc2d57..15d1598b9 100644 --- a/recursion/gnark-ffi/build.rs +++ b/recursion/gnark-ffi/build.rs @@ -11,7 +11,7 @@ use bindgen::CargoCallbacks; /// Build the go library, generate Rust bindings for the exposed functions, and link the library. fn main() { cfg_if! { - if #[cfg(feature = "plonk")] { + if #[cfg(feature = "native")] { println!("cargo:rerun-if-changed=go"); // Define the output directory let out_dir = env::var("OUT_DIR").unwrap(); diff --git a/recursion/gnark-ffi/go/sp1/prove.go b/recursion/gnark-ffi/go/sp1/prove.go index c921d1143..4a7149239 100644 --- a/recursion/gnark-ffi/go/sp1/prove.go +++ b/recursion/gnark-ffi/go/sp1/prove.go @@ -1,6 +1,7 @@ package sp1 import ( + "bufio" "encoding/json" "os" @@ -30,7 +31,8 @@ func Prove(dataDir string, witnessPath string) Proof { panic(err) } pk := plonk.NewProvingKey(ecc.BN254) - pk.UnsafeReadFrom(pkFile) + bufReader := bufio.NewReaderSize(pkFile, 1024*1024) + pk.UnsafeReadFrom(bufReader) // Read the verifier key. vkFile, err := os.Open(dataDir + "/" + VK_PATH) diff --git a/recursion/gnark-ffi/src/ffi.rs b/recursion/gnark-ffi/src/ffi.rs deleted file mode 100644 index d9421f3ab..000000000 --- a/recursion/gnark-ffi/src/ffi.rs +++ /dev/null @@ -1,176 +0,0 @@ -#![allow(unused)] - -//! FFI bindings for the Go code. The functions exported in this module are safe to call from Rust. -//! All C strings and other C memory should be freed in Rust, including C Strings returned by Go. -//! Although we cast to *mut c_char because the Go signatures can't be immutable, the Go functions -//! should not modify the strings. - -use crate::PlonkBn254Proof; -use cfg_if::cfg_if; -use std::ffi::{c_char, CString}; - -#[allow(warnings, clippy::all)] -mod bind { - #[cfg(feature = "plonk")] - include!(concat!(env!("OUT_DIR"), "/bindings.rs")); -} -use bind::*; - -pub fn prove_plonk_bn254(data_dir: &str, witness_path: &str) -> PlonkBn254Proof { - cfg_if! { - if #[cfg(feature = "plonk")] { - let data_dir = CString::new(data_dir).expect("CString::new failed"); - let witness_path = CString::new(witness_path).expect("CString::new failed"); - - let proof = unsafe { - let proof = ProvePlonkBn254( - data_dir.as_ptr() as *mut c_char, - witness_path.as_ptr() as *mut c_char, - ); - // Safety: The pointer is returned from the go code and is guaranteed to be valid. - *proof - }; - - proof.into_rust() - } else { - panic!("plonk feature not enabled"); - } - } -} - -pub fn build_plonk_bn254(data_dir: &str) { - cfg_if! { - if #[cfg(feature = "plonk")] { - let data_dir = CString::new(data_dir).expect("CString::new failed"); - - unsafe { - BuildPlonkBn254(data_dir.as_ptr() as *mut c_char); - } - } else { - panic!("plonk feature not enabled"); - - } - } -} - -pub fn verify_plonk_bn254( - data_dir: &str, - proof: &str, - vkey_hash: &str, - committed_values_digest: &str, -) -> Result<(), String> { - cfg_if! { - if #[cfg(feature = "plonk")] { - let data_dir = CString::new(data_dir).expect("CString::new failed"); - let proof = CString::new(proof).expect("CString::new failed"); - let vkey_hash = CString::new(vkey_hash).expect("CString::new failed"); - let committed_values_digest = - CString::new(committed_values_digest).expect("CString::new failed"); - - let err_ptr = unsafe { - VerifyPlonkBn254( - data_dir.as_ptr() as *mut c_char, - proof.as_ptr() as *mut c_char, - vkey_hash.as_ptr() as *mut c_char, - committed_values_digest.as_ptr() as *mut c_char, - ) - }; - if err_ptr.is_null() { - Ok(()) - } else { - // Safety: The error message is returned from the go code and is guaranteed to be valid. - let err = unsafe { CString::from_raw(err_ptr) }; - Err(err.into_string().unwrap()) - } - } else { - panic!("plonk feature not enabled"); - } - } -} - -pub fn test_plonk_bn254(witness_json: &str, constraints_json: &str) { - cfg_if! { - if #[cfg(feature = "plonk")] { - unsafe { - let witness_json = CString::new(witness_json).expect("CString::new failed"); - let build_dir = CString::new(constraints_json).expect("CString::new failed"); - let err_ptr = TestPlonkBn254( - witness_json.as_ptr() as *mut c_char, - build_dir.as_ptr() as *mut c_char, - ); - if !err_ptr.is_null() { - // Safety: The error message is returned from the go code and is guaranteed to be valid. - let err = CString::from_raw(err_ptr); - panic!("TestPlonkBn254 failed: {}", err.into_string().unwrap()); - } - } - } else { - panic!("plonk feature not enabled"); - } - } -} - -pub fn test_babybear_poseidon2() { - cfg_if! { - if #[cfg(feature = "plonk")] { - unsafe { - let err_ptr = bind::TestPoseidonBabyBear2(); - if !err_ptr.is_null() { - // Safety: The error message is returned from the go code and is guaranteed to be valid. - let err = CString::from_raw(err_ptr); - panic!("TestPlonkBn254 failed: {}", err.into_string().unwrap()); - } - } - } else { - panic!("plonk feature not enabled"); - } - } -} - -/// Converts a C string into a Rust String. -/// -/// # Safety -/// This function frees the string memory, so the caller must ensure that the pointer is not used -/// after this function is called. -unsafe fn c_char_ptr_to_string(input: *mut c_char) -> String { - unsafe { - CString::from_raw(input) // Converts a pointer that C uses into a CString - .into_string() - .expect("CString::into_string failed") - } -} - -#[cfg(feature = "plonk")] -impl C_PlonkBn254Proof { - /// Converts a C PlonkBn254Proof into a Rust PlonkBn254Proof, freeing the C strings. - fn into_rust(self) -> PlonkBn254Proof { - // Safety: The raw pointers are not used anymore after converted into Rust strings. - unsafe { - PlonkBn254Proof { - public_inputs: [ - c_char_ptr_to_string(self.PublicInputs[0]), - c_char_ptr_to_string(self.PublicInputs[1]), - ], - encoded_proof: c_char_ptr_to_string(self.EncodedProof), - raw_proof: c_char_ptr_to_string(self.RawProof), - } - } - } -} - -#[cfg(test)] -mod tests { - use p3_baby_bear::BabyBear; - use p3_field::AbstractField; - use p3_symmetric::Permutation; - - #[cfg(feature = "plonk")] - #[test] - pub fn test_babybear_poseidon2() { - let perm = sphinx_core::utils::inner_perm(); - let zeros = [BabyBear::zero(); 16]; - let result = perm.permute(zeros); - println!("{:?}", result); - super::test_babybear_poseidon2(); - } -} diff --git a/recursion/gnark-ffi/src/ffi/docker.rs b/recursion/gnark-ffi/src/ffi/docker.rs new file mode 100644 index 000000000..9afdd552b --- /dev/null +++ b/recursion/gnark-ffi/src/ffi/docker.rs @@ -0,0 +1,114 @@ +use sphinx_core::SPHINX_CIRCUIT_VERSION; + +use crate::PlonkBn254Proof; +use std::io::Write; +use std::process::Command; + +/// Checks that docker is installed and running. +fn check_docker() -> bool { + let output = Command::new("docker").arg("info").output(); + output.is_ok() && output.unwrap().status.success() +} + +/// Panics if docker is not installed and running. +fn assert_docker() { + if !check_docker() { + panic!("Failed to run `docker info`. Please ensure that docker is installed and running."); + } +} + +fn get_docker_image() -> String { + std::env::var("SPHINX_GNARK_IMAGE") + .unwrap_or_else(|_| format!("ghcr.io/succinctlabs/sp1-gnark:{}", SPHINX_CIRCUIT_VERSION)) +} + +/// Calls `docker run` with the given arguments and bind mounts. +fn call_docker(args: &[&str], mounts: &[(&str, &str)]) -> anyhow::Result<()> { + log::info!("Running {} in docker", args[0]); + let mut cmd = Command::new("docker"); + cmd.args(["run", "--rm"]); + for (src, dest) in mounts { + cmd.arg("-v").arg(format!("{}:{}", src, dest)); + } + cmd.arg(get_docker_image()); + cmd.args(args); + if !cmd.status()?.success() { + log::error!("Failed to run `docker run`: {:?}", cmd); + return Err(anyhow::anyhow!("docker command failed")); + } + Ok(()) +} + +pub fn prove_plonk_bn254(data_dir: &str, witness_path: &str) -> PlonkBn254Proof { + let output_file = tempfile::NamedTempFile::new().unwrap(); + let mounts = [ + (data_dir, "/circuit"), + (witness_path, "/witness"), + (output_file.path().to_str().unwrap(), "/output"), + ]; + assert_docker(); + call_docker(&["prove-plonk", "/circuit", "/witness", "/output"], &mounts) + .expect("failed to prove with docker"); + bincode::deserialize_from(&output_file).expect("failed to deserialize result") +} + +pub fn build_plonk_bn254(data_dir: &str) { + let circuit_dir = if data_dir.ends_with("dev") { + "/circuit_dev" + } else { + "/circuit" + }; + let mounts = [(data_dir, circuit_dir)]; + assert_docker(); + call_docker(&["build-plonk", circuit_dir], &mounts).expect("failed to build with docker"); +} + +pub fn verify_plonk_bn254( + data_dir: &str, + proof: &str, + vkey_hash: &str, + committed_values_digest: &str, +) -> Result<(), String> { + // Write proof string to a file since it can be large. + let mut proof_file = tempfile::NamedTempFile::new().unwrap(); + proof_file.write_all(proof.as_bytes()).unwrap(); + let output_file = tempfile::NamedTempFile::new().unwrap(); + let mounts = [ + (data_dir, "/circuit"), + (proof_file.path().to_str().unwrap(), "/proof"), + (output_file.path().to_str().unwrap(), "/output"), + ]; + assert_docker(); + call_docker( + &[ + "verify-plonk", + "/circuit", + "/proof", + vkey_hash, + committed_values_digest, + "/output", + ], + &mounts, + ) + .expect("failed to verify with docker"); + let result = std::fs::read_to_string(output_file.path()).unwrap(); + if result == "OK" { + Ok(()) + } else { + Err(result) + } +} + +pub fn test_plonk_bn254(witness_json: &str, constraints_json: &str) { + let mounts = [ + (constraints_json, "/constraints"), + (witness_json, "/witness"), + ]; + assert_docker(); + call_docker(&["test-plonk", "/constraints", "/witness"], &mounts) + .expect("failed to test with docker"); +} + +pub fn test_babybear_poseidon2() { + unimplemented!() +} diff --git a/recursion/gnark-ffi/src/ffi/mod.rs b/recursion/gnark-ffi/src/ffi/mod.rs new file mode 100644 index 000000000..42358f90e --- /dev/null +++ b/recursion/gnark-ffi/src/ffi/mod.rs @@ -0,0 +1,9 @@ +cfg_if::cfg_if! { + if #[cfg(feature = "native")] { + mod native; + pub use native::*; + } else { + mod docker; + pub use docker::*; + } +} diff --git a/recursion/gnark-ffi/src/ffi/native.rs b/recursion/gnark-ffi/src/ffi/native.rs new file mode 100644 index 000000000..3e733cdd3 --- /dev/null +++ b/recursion/gnark-ffi/src/ffi/native.rs @@ -0,0 +1,144 @@ +#![allow(unused)] + +//! FFI bindings for the Go code. The functions exported in this module are safe to call from Rust. +//! All C strings and other C memory should be freed in Rust, including C Strings returned by Go. +//! Although we cast to *mut c_char because the Go signatures can't be immutable, the Go functions +//! should not modify the strings. + +use crate::PlonkBn254Proof; +use cfg_if::cfg_if; +use sphinx_core::SPHINX_CIRCUIT_VERSION; +use std::ffi::{c_char, CString}; + +#[allow(warnings, clippy::all)] +mod bind { + include!(concat!(env!("OUT_DIR"), "/bindings.rs")); +} +use bind::*; + +pub fn prove_plonk_bn254(data_dir: &str, witness_path: &str) -> PlonkBn254Proof { + let data_dir = CString::new(data_dir).expect("CString::new failed"); + let witness_path = CString::new(witness_path).expect("CString::new failed"); + + let proof = unsafe { + let proof = ProvePlonkBn254( + data_dir.as_ptr() as *mut c_char, + witness_path.as_ptr() as *mut c_char, + ); + // Safety: The pointer is returned from the go code and is guaranteed to be valid. + *proof + }; + + proof.into_rust() +} + +pub fn build_plonk_bn254(data_dir: &str) { + let data_dir = CString::new(data_dir).expect("CString::new failed"); + + unsafe { + BuildPlonkBn254(data_dir.as_ptr() as *mut c_char); + } +} + +pub fn verify_plonk_bn254( + data_dir: &str, + proof: &str, + vkey_hash: &str, + committed_values_digest: &str, +) -> Result<(), String> { + let data_dir = CString::new(data_dir).expect("CString::new failed"); + let proof = CString::new(proof).expect("CString::new failed"); + let vkey_hash = CString::new(vkey_hash).expect("CString::new failed"); + let committed_values_digest = + CString::new(committed_values_digest).expect("CString::new failed"); + + let err_ptr = unsafe { + VerifyPlonkBn254( + data_dir.as_ptr() as *mut c_char, + proof.as_ptr() as *mut c_char, + vkey_hash.as_ptr() as *mut c_char, + committed_values_digest.as_ptr() as *mut c_char, + ) + }; + if err_ptr.is_null() { + Ok(()) + } else { + // Safety: The error message is returned from the go code and is guaranteed to be valid. + let err = unsafe { CString::from_raw(err_ptr) }; + Err(err.into_string().unwrap()) + } +} + +pub fn test_plonk_bn254(witness_json: &str, constraints_json: &str) { + unsafe { + let witness_json = CString::new(witness_json).expect("CString::new failed"); + let build_dir = CString::new(constraints_json).expect("CString::new failed"); + let err_ptr = TestPlonkBn254( + witness_json.as_ptr() as *mut c_char, + build_dir.as_ptr() as *mut c_char, + ); + if !err_ptr.is_null() { + // Safety: The error message is returned from the go code and is guaranteed to be valid. + let err = CString::from_raw(err_ptr); + panic!("TestPlonkBn254 failed: {}", err.into_string().unwrap()); + } + } +} + +pub fn test_babybear_poseidon2() { + unsafe { + let err_ptr = TestPoseidonBabyBear2(); + if !err_ptr.is_null() { + // Safety: The error message is returned from the go code and is guaranteed to be valid. + let err = CString::from_raw(err_ptr); + panic!("TestPlonkBn254 failed: {}", err.into_string().unwrap()); + } + } +} + +/// Converts a C string into a Rust String. +/// +/// # Safety +/// This function frees the string memory, so the caller must ensure that the pointer is not used +/// after this function is called. +unsafe fn c_char_ptr_to_string(input: *mut c_char) -> String { + unsafe { + CString::from_raw(input) // Converts a pointer that C uses into a CString + .into_string() + .expect("CString::into_string failed") + } +} + +impl C_PlonkBn254Proof { + /// Converts a C PlonkBn254Proof into a Rust PlonkBn254Proof, freeing the C strings. + fn into_rust(self) -> PlonkBn254Proof { + // Safety: The raw pointers are not used anymore after converted into Rust strings. + unsafe { + PlonkBn254Proof { + public_inputs: [ + c_char_ptr_to_string(self.PublicInputs[0]), + c_char_ptr_to_string(self.PublicInputs[1]), + ], + encoded_proof: c_char_ptr_to_string(self.EncodedProof), + raw_proof: c_char_ptr_to_string(self.RawProof), + plonk_vkey_hash: [0; 32], + } + } + } +} + +#[cfg(test)] +mod tests { + use p3_baby_bear::BabyBear; + use p3_field::AbstractField; + use p3_symmetric::Permutation; + + #[test] + pub(crate) fn test_babybear_poseidon2() { + let perm = sphinx_core::utils::inner_perm(); + let zeros = [BabyBear::zero(); 16]; + let result = perm.permute(zeros); + println!("{:?}", result); + super::test_babybear_poseidon2(); + } +} diff --git a/recursion/gnark-ffi/src/lib.rs b/recursion/gnark-ffi/src/lib.rs index 26940e863..670a9b08f 100644 --- a/recursion/gnark-ffi/src/lib.rs +++ b/recursion/gnark-ffi/src/lib.rs @@ -1,5 +1,7 @@ mod babybear; + pub mod ffi; + pub mod plonk_bn254; pub mod witness; diff --git a/recursion/gnark-ffi/src/plonk_bn254.rs b/recursion/gnark-ffi/src/plonk_bn254.rs index 26ba0fcba..4d84591d7 100644 --- a/recursion/gnark-ffi/src/plonk_bn254.rs +++ b/recursion/gnark-ffi/src/plonk_bn254.rs @@ -1,12 +1,13 @@ use std::{fs::File, io::Write, path::Path}; -use crate::{ - ffi::{build_plonk_bn254, prove_plonk_bn254, test_plonk_bn254, verify_plonk_bn254}, - witness::GnarkWitness, -}; +use crate::ffi::{build_plonk_bn254, prove_plonk_bn254, test_plonk_bn254, verify_plonk_bn254}; +use crate::witness::GnarkWitness; use num_bigint::BigUint; use serde::{Deserialize, Serialize}; +use sha2::Digest; +use sha2::Sha256; +use sphinx_core::SPHINX_CIRCUIT_VERSION; use sphinx_recursion_compiler::{ constraints::Constraint, ir::{Config, Witness}, @@ -22,6 +23,7 @@ pub struct PlonkBn254Proof { pub public_inputs: [String; 2], pub encoded_proof: String, pub raw_proof: String, + pub plonk_vkey_hash: [u8; 32], } impl PlonkBn254Prover { @@ -30,6 +32,12 @@ impl PlonkBn254Prover { Self } + pub fn get_vkey_hash(build_dir: &Path) -> [u8; 32] { + let vkey_path = build_dir.join("vk.bin"); + let vk_bin_bytes = std::fs::read(vkey_path).unwrap(); + Sha256::digest(vk_bin_bytes).into() + } + /// Executes the prover in testing mode with a circuit definition and witness. pub fn test(constraints: &[Constraint], witness: Witness) { let serialized = serde_json::to_string(&constraints).unwrap(); @@ -77,7 +85,13 @@ impl PlonkBn254Prover { .unwrap(); let sphinx_verifier_path = build_dir.join("SphinxVerifier.sol"); - let sphinx_verifier_str = include_str!("../assets/SphinxVerifier.txt"); + let vkey_hash = Self::get_vkey_hash(build_dir); + let sphinx_verifier_str = include_str!("../assets/SphinxVerifier.txt") + .replace("{SPHINX_CIRCUIT_VERSION}", SPHINX_CIRCUIT_VERSION) + .replace( + "{VKEY_HASH}", + format!("0x{}", hex::encode(vkey_hash)).as_str(), + ); let mut sphinx_verifier_file = File::create(sphinx_verifier_path).unwrap(); sphinx_verifier_file .write_all(sphinx_verifier_str.as_bytes()) @@ -92,7 +106,7 @@ impl PlonkBn254Prover { .unwrap(); } - /// Generates a PLONK proof by sending a request to the Gnark server. + /// Generates a PLONK proof given a witness. pub fn prove(&self, witness: Witness, build_dir: &Path) -> PlonkBn254Proof { // Write witness. let mut witness_file = tempfile::NamedTempFile::new().unwrap(); @@ -100,10 +114,12 @@ impl PlonkBn254Prover { let serialized = serde_json::to_string(&gnark_witness).unwrap(); witness_file.write_all(serialized.as_bytes()).unwrap(); - prove_plonk_bn254( + let mut proof = prove_plonk_bn254( build_dir.to_str().unwrap(), witness_file.path().to_str().unwrap(), - ) + ); + proof.plonk_vkey_hash = Self::get_vkey_hash(build_dir); + proof } /// Verify a PLONK proof and verify that the supplied vkey_hash and committed_values_digest match. @@ -114,6 +130,7 @@ impl PlonkBn254Prover { committed_values_digest: &BigUint, build_dir: &Path, ) { + assert!(proof.plonk_vkey_hash == Self::get_vkey_hash(build_dir), "Proof vkey hash does not match circuit vkey hash, it was generated with a different circuit."); verify_plonk_bn254( build_dir.to_str().unwrap(), &proof.raw_proof, diff --git a/recursion/program/src/constraints.rs b/recursion/program/src/constraints.rs index 9c64bb56d..6f7189237 100644 --- a/recursion/program/src/constraints.rs +++ b/recursion/program/src/constraints.rs @@ -159,6 +159,7 @@ mod tests { use p3_challenger::{CanObserve, FieldChallenger}; use p3_commit::{Pcs, PolynomialSpace}; use p3_field::PrimeField32; + use rand::Rng; use serde::{de::DeserializeOwned, Serialize}; use sphinx_core::{ io::SphinxStdin, @@ -171,7 +172,7 @@ mod tests { }; use sphinx_recursion_core::stark::utils::{run_test_recursion, TestConfig}; - use sphinx_recursion_compiler::{asm::AsmBuilder, prelude::ExtConst}; + use sphinx_recursion_compiler::{asm::AsmBuilder, ir::Felt, prelude::ExtConst}; fn get_shard_data<'a, SC>( machine: &'a StarkMachine>, @@ -350,4 +351,33 @@ mod tests { let program = builder.compile_program(); run_test_recursion(&program, None, TestConfig::All); } + + #[test] + fn test_exp_reverse_bit_len_fast() { + type SC = BabyBearPoseidon2; + type F = ::Val; + type EF = ::Challenge; + + let mut rng = rand::thread_rng(); + + // Initialize a builder. + let mut builder = AsmBuilder::::default(); + + // Get a random var with `NUM_BITS` bits. + let x_val: F = rng.gen(); + + // Materialize the number as a var + let x_felt: Felt<_> = builder.eval(x_val); + let x_bits = builder.num2bits_f(x_felt); + + let result = builder.exp_reverse_bits_len_fast(x_felt, &x_bits, 5); + let expected_val = builder.exp_reverse_bits_len(x_felt, &x_bits, 5); + + builder.assert_felt_eq(expected_val, result); + builder.halt(); + + let program = builder.compile_program(); + + run_test_recursion(&program, None, TestConfig::All); + } } diff --git a/recursion/program/src/fri/mod.rs b/recursion/program/src/fri/mod.rs index 83741947e..9168485ef 100644 --- a/recursion/program/src/fri/mod.rs +++ b/recursion/program/src/fri/mod.rs @@ -136,10 +136,7 @@ where let folded_eval: Ext = builder.eval(C::F::zero()); let two_adic_generator_f = config.get_two_adic_generator(builder, log_max_height); - let two_adic_gen_ext = two_adic_generator_f.to_operand().symbolic(); - let two_adic_generator_ef: Ext<_, _> = builder.eval(two_adic_gen_ext); - - let x = builder.exp_reverse_bits_len(two_adic_generator_ef, index_bits, log_max_height); + let x = builder.exp_reverse_bits_len_fast(two_adic_generator_f, index_bits, log_max_height); let log_max_height = log_max_height.materialize(builder); builder @@ -189,10 +186,10 @@ where .if_eq(index_sibling_mod_2, C::N::zero()) .then_or_else( |builder| { - builder.assign(&xs_0, x * two_adic_generator_one); + builder.assign(&xs_0, x * two_adic_generator_one.to_operand().symbolic()); }, |builder| { - builder.assign(&xs_1, x * two_adic_generator_one); + builder.assign(&xs_1, x * two_adic_generator_one.to_operand().symbolic()); }, ); diff --git a/recursion/program/src/fri/two_adic_pcs.rs b/recursion/program/src/fri/two_adic_pcs.rs index 9164ed560..aa4815eef 100644 --- a/recursion/program/src/fri/two_adic_pcs.rs +++ b/recursion/program/src/fri/two_adic_pcs.rs @@ -118,7 +118,7 @@ pub fn verify_two_adic_pcs( let two_adic_generator = config.get_two_adic_generator(builder, log_height); builder.cycle_tracker("exp_reverse_bits_len"); - let two_adic_generator_exp = builder.exp_reverse_bits_len( + let two_adic_generator_exp = builder.exp_reverse_bits_len_fast( two_adic_generator, &index_bits_shifted, log_height, diff --git a/recursion/program/src/machine/deferred.rs b/recursion/program/src/machine/deferred.rs index 67fe6f4d2..13e5343c0 100644 --- a/recursion/program/src/machine/deferred.rs +++ b/recursion/program/src/machine/deferred.rs @@ -115,7 +115,7 @@ where /// verifier: /// - Asserts that each of these proofs is valid as a `compress` proof. /// - Asserts that each of these proofs is complete by checking the `is_complete` flag in the - /// proof's public values. + /// proof's public values. /// - Aggregates the proof information into the accumulated deferred digest. pub fn verify( builder: &mut Builder, diff --git a/recursion/program/src/stark.rs b/recursion/program/src/stark.rs index 872785760..7b490593c 100644 --- a/recursion/program/src/stark.rs +++ b/recursion/program/src/stark.rs @@ -3,6 +3,8 @@ use p3_commit::TwoAdicMultiplicativeCoset; use p3_field::AbstractField; use p3_field::TwoAdicField; use sphinx_core::air::MachineAir; +use sphinx_core::air::PublicValues; +use sphinx_core::air::Word; use sphinx_core::stark::Com; use sphinx_core::stark::GenericVerifierConstraintFolder; use sphinx_core::stark::ShardProof; @@ -133,6 +135,14 @@ where .. } = proof; + // Extract public values. + let mut pv_elements = Vec::new(); + for i in 0..machine.num_pv_elts() { + let element = builder.get(&proof.public_values, i); + pv_elements.push(element); + } + let public_values = PublicValues::>, Felt<_>>::from_vec(&pv_elements); + let ShardCommitmentVariable { main_commit, permutation_commit, @@ -302,52 +312,42 @@ where builder.cycle_tracker("stage-d-verify-pcs"); builder.cycle_tracker("stage-e-verify-constraints"); + + let shard_bits = builder.num2bits_f(public_values.shard); + let shard = builder.bits2num_v(&shard_bits); for (i, chip) in machine.chips().iter().enumerate() { tracing::debug!("verifying constraints for chip: {}", chip.as_ref().name()); let index = builder.get(&proof.sorted_idxs, i); - if chip.as_ref().preprocessed_width() > 0 { + if chip.as_ref().name() == "CPU" { builder.assert_var_ne(index, C::N::from_canonical_usize(EMPTY)); } - if chip.as_ref().name() == "CPU" { + if chip.as_ref().preprocessed_width() > 0 { builder.assert_var_ne(index, C::N::from_canonical_usize(EMPTY)); } - // TODO(wwared): Update and uncomment these constraints with future security ports, see issue #38 - if chip.as_ref().name() == "MemoryProgram" { - builder.assert_var_ne(index, C::N::from_canonical_usize(EMPTY)); - // builder.if_eq(shard_idx, C::N::one()).then_or_else( - // |builder| { - // builder.assert_var_ne(index, C::N::from_canonical_usize(EMPTY)); - // }, - // |builder| { - // builder.assert_var_eq(index, C::N::from_canonical_usize(EMPTY)); - // }, - // ); + if chip.as_ref().name() == "MemoryInit" { + builder.if_eq(shard, C::N::one()).then_or_else( + |builder| { + builder.assert_var_ne(index, C::N::from_canonical_usize(EMPTY)); + }, + |builder| { + builder.assert_var_eq(index, C::N::from_canonical_usize(EMPTY)); + }, + ); } - // if chip.as_ref().name() == "MemoryInit" { - // builder.if_eq(shard_idx, C::N::one()).then_or_else( - // |builder| { - // builder.assert_var_ne(index, C::N::from_canonical_usize(EMPTY)); - // }, - // |builder| { - // builder.assert_var_eq(index, C::N::from_canonical_usize(EMPTY)); - // }, - // ); - // } - - // if chip.as_ref().name() == "MemoryFinalize" { - // builder.if_eq(shard_idx, C::N::one()).then_or_else( - // |builder| { - // builder.assert_var_ne(index, C::N::from_canonical_usize(EMPTY)); - // }, - // |builder| { - // builder.assert_var_eq(index, C::N::from_canonical_usize(EMPTY)); - // }, - // ); - // } + if chip.as_ref().name() == "MemoryFinalize" { + builder.if_eq(shard, C::N::one()).then_or_else( + |builder| { + builder.assert_var_ne(index, C::N::from_canonical_usize(EMPTY)); + }, + |builder| { + builder.assert_var_eq(index, C::N::from_canonical_usize(EMPTY)); + }, + ); + } builder .if_ne(index, C::N::from_canonical_usize(EMPTY)) diff --git a/sdk/Cargo.toml b/sdk/Cargo.toml index c24a08e06..2da06891c 100644 --- a/sdk/Cargo.toml +++ b/sdk/Cargo.toml @@ -12,7 +12,7 @@ serde_json = { workspace = true } twirp = { workspace = true } async-trait = { workspace = true } reqwest-middleware = { workspace = true } -reqwest = { workspace = true, features = ["default-tls", "trust-dns", "stream"] } +reqwest = { workspace = true, features = ["rustls-tls", "trust-dns", "stream"] } anyhow = { workspace = true } sphinx-prover = { path = "../prover" } sphinx-core = { path = "../core" } @@ -36,6 +36,7 @@ cfg-if = { workspace = true } ethers = { workspace = true } strum_macros = { workspace = true } strum = { workspace = true } +thiserror = { workspace = true } [features] default = ["network"] diff --git a/sdk/src/lib.rs b/sdk/src/lib.rs index 901d355a0..92c63c1f3 100644 --- a/sdk/src/lib.rs +++ b/sdk/src/lib.rs @@ -21,6 +21,7 @@ pub mod utils { } use cfg_if::cfg_if; +pub use provers::SphinxVerificationError; use std::{env, fmt::Debug, fs::File, path::Path}; use anyhow::{Ok, Result}; @@ -31,6 +32,7 @@ use serde::{de::DeserializeOwned, Deserialize, Serialize}; use sphinx_core::{ runtime::ExecutionReport, stark::{MachineVerificationError, ShardProof}, + SPHINX_CIRCUIT_VERSION, }; pub use sphinx_prover::{ types::HashableKey, types::SphinxProvingKey, types::SphinxVerifyingKey, CoreSC, InnerSC, @@ -51,6 +53,7 @@ pub struct SphinxProofWithPublicValues

{ pub proof: P, pub stdin: SphinxStdin, pub public_values: SphinxPublicValues, + pub sphinx_version: String, } /// A [SP1ProofWithPublicValues] generated with [ProverClient::prove]. @@ -102,7 +105,7 @@ impl ProverClient { panic!("network feature is not enabled") } } - }, + } _ => panic!( "invalid value for SP1_PROVER enviroment variable: expected 'local', 'mock', or 'network'" ), @@ -169,6 +172,13 @@ impl ProverClient { } } + /// Gets the current version of the SP1 zkVM. + /// + /// Note: This is not the same as the version of the SP1 SDK. + pub fn version(&self) -> String { + SPHINX_CIRCUIT_VERSION.to_string() + } + /// Executes the given program on the given input (without generating a proof). /// /// Returns the public values and execution report of the program after it has been executed. @@ -335,7 +345,7 @@ impl ProverClient { &self, proof: &SphinxProof, vkey: &SphinxVerifyingKey, - ) -> Result<(), SphinxProofVerificationError> { + ) -> Result<(), SphinxVerificationError> { self.prover.verify(proof, vkey) } @@ -367,7 +377,7 @@ impl ProverClient { &self, proof: &SphinxCompressedProof, vkey: &SphinxVerifyingKey, - ) -> Result<()> { + ) -> Result<(), SphinxVerificationError> { self.prover.verify_compressed(proof, vkey) } @@ -401,7 +411,7 @@ impl ProverClient { &self, proof: &SphinxPlonkBn254Proof, vkey: &SphinxVerifyingKey, - ) -> Result<()> { + ) -> Result<(), SphinxVerificationError> { self.prover.verify_plonk(proof, vkey) } } @@ -427,8 +437,13 @@ impl SphinxProofWithPublicValue } impl SphinxPlonkBn254Proof { + /// Returns the encoded proof bytes with a prefix of the VK hash. pub fn bytes(&self) -> String { - format!("0x{}", self.proof.encoded_proof.clone()) + format!( + "0x{}{}", + hex::encode(&self.proof.plonk_vkey_hash[..4]), + &self.proof.encoded_proof + ) } } diff --git a/sdk/src/network/prover.rs b/sdk/src/network/prover.rs index 9f884d3e7..065674d7a 100644 --- a/sdk/src/network/prover.rs +++ b/sdk/src/network/prover.rs @@ -3,18 +3,17 @@ use std::{env, time::Duration}; use crate::proto::network::ProofMode; use crate::{ network::client::{NetworkClient, DEFAULT_PROVER_NETWORK_RPC}, - proto::network::{ProofStatus, TransactionStatus}, + proto::network::ProofStatus, Prover, }; use crate::{ SphinxCompressedProof, SphinxPlonkBn254Proof, SphinxProof, SphinxProvingKey, SphinxVerifyingKey, }; -use anyhow::{Context, Result}; +use anyhow::Result; use serde::de::DeserializeOwned; -use sphinx_prover::install::PLONK_BN254_ARTIFACTS_COMMIT; use sphinx_prover::utils::block_on; -use sphinx_prover::{SphinxProver, SphinxStdin}; -use tokio::{runtime, time::sleep}; +use sphinx_prover::{SphinxProver, SphinxStdin, SPHINX_CIRCUIT_VERSION}; +use tokio::time::sleep; use crate::provers::{LocalProver, ProverType}; @@ -25,23 +24,32 @@ pub struct NetworkProver { } impl NetworkProver { - /// Creates a new [NetworkProver]. + /// Creates a new [NetworkProver] with the private key set in `SP1_PRIVATE_KEY`. pub fn new() -> Self { let private_key = env::var("SP1_PRIVATE_KEY") .unwrap_or_else(|_| panic!("SP1_PRIVATE_KEY must be set for remote proving")); + Self::new_from_key(&private_key) + } + + /// Creates a new [NetworkProver] with the given private key. + pub fn new_from_key(private_key: &str) -> Self { + let version = SPHINX_CIRCUIT_VERSION; + log::info!("Client circuit version: {}", version); + let local_prover = LocalProver::new(); Self { - client: NetworkClient::new(&private_key), + client: NetworkClient::new(private_key), local_prover, } } - pub(crate) async fn prove_async( + /// Requests a proof from the prover network, returning the proof ID. + pub async fn request_proof( &self, elf: &[u8], stdin: SphinxStdin, mode: ProofMode, - ) -> Result

{ + ) -> Result { let client = &self.client; let skip_simulation = env::var("SKIP_SIMULATION") @@ -58,22 +66,25 @@ impl NetworkProver { log::info!("Skipping simulation"); } - let version = PLONK_BN254_ARTIFACTS_COMMIT; - log::info!("Client version {}", version); - + let version = SPHINX_CIRCUIT_VERSION; let proof_id = client.create_proof(elf, &stdin, mode, version).await?; log::info!("Created {}", proof_id); if NetworkClient::rpc_url() == DEFAULT_PROVER_NETWORK_RPC { log::info!( "View in explorer: https://explorer.succinct.xyz/{}", - proof_id.split('_').last().unwrap_or(&proof_id) + proof_id ); } + Ok(proof_id) + } + /// Waits for a proof to be generated and returns the proof. + pub async fn wait_proof(&self, proof_id: &str) -> Result

{ + let client = &self.client; let mut is_claimed = false; loop { - let (status, maybe_proof) = client.get_proof_status::

(&proof_id).await?; + let (status, maybe_proof) = client.get_proof_status::

(proof_id).await?; match status.status() { ProofStatus::ProofFulfilled => { @@ -97,68 +108,10 @@ impl NetworkProver { } } - #[allow(dead_code)] - /// Remotely relay a proof to a set of chains with their callback contracts. - pub(crate) fn remote_relay( - &self, - proof_id: &str, - chain_ids: &[u32], - callbacks: &[[u8; 20]], - callback_datas: &[Vec], - ) -> Result> { - let rt = runtime::Runtime::new()?; - rt.block_on(async { - let client = &self.client; - - let verifier = NetworkClient::get_sphinx_verifier_address(); - - let mut tx_details = Vec::new(); - for ((i, callback), callback_data) in - callbacks.iter().enumerate().zip(callback_datas.iter()) - { - if let Some(&chain_id) = chain_ids.get(i) { - let tx_id = client - .relay_proof(proof_id, chain_id, verifier, *callback, callback_data) - .await - .with_context(|| format!("Failed to relay proof to chain {}", chain_id))?; - tx_details.push((tx_id.clone(), chain_id)); - } - } - - let mut tx_ids = Vec::new(); - for (tx_id, chain_id) in tx_details.iter() { - loop { - let (status_res, maybe_tx_hash, maybe_simulation_url) = - client.get_relay_status(tx_id).await?; - - match status_res.status() { - TransactionStatus::TransactionFinalized => { - println!( - "Relaying to chain {} succeeded with tx hash: {:?}", - chain_id, - maybe_tx_hash.as_deref().unwrap_or("None") - ); - tx_ids.push(tx_id.clone()); - break; - } - TransactionStatus::TransactionFailed - | TransactionStatus::TransactionTimedout => { - return Err(anyhow::anyhow!( - "Relaying to chain {} failed with tx hash: {:?}, simulation url: {:?}", - chain_id, - maybe_tx_hash.as_deref().unwrap_or("None"), - maybe_simulation_url.as_deref().unwrap_or("None") - )); - } - _ => { - sleep(Duration::from_secs(5)).await; - } - } - } - } - - Ok(tx_ids) - }) + /// Requests a proof from the prover network and waits for it to be generated. + pub async fn prove(&self, elf: &[u8], stdin: SphinxStdin) -> Result

{ + let proof_id = self.request_proof(elf, stdin, P::PROOF_MODE).await?; + self.wait_proof(&proof_id).await } } @@ -176,7 +129,7 @@ impl Prover for NetworkProver { } fn prove(&self, pk: &SphinxProvingKey, stdin: SphinxStdin) -> Result { - block_on(self.prove_async(&pk.elf, stdin, ProofMode::Core)) + block_on(self.prove(&pk.elf, stdin)) } fn prove_compressed( @@ -184,7 +137,7 @@ impl Prover for NetworkProver { pk: &SphinxProvingKey, stdin: SphinxStdin, ) -> Result { - block_on(self.prove_async(&pk.elf, stdin, ProofMode::Compressed)) + block_on(self.prove(&pk.elf, stdin)) } fn prove_plonk( @@ -192,7 +145,7 @@ impl Prover for NetworkProver { pk: &SphinxProvingKey, stdin: SphinxStdin, ) -> Result { - block_on(self.prove_async(&pk.elf, stdin, ProofMode::Plonk)) + block_on(self.prove(&pk.elf, stdin)) } } @@ -201,3 +154,20 @@ impl Default for NetworkProver { Self::new() } } + +/// A deserializable proof struct that has an associated ProofMode. +pub trait ProofType: DeserializeOwned { + const PROOF_MODE: ProofMode; +} + +impl ProofType for SphinxProof { + const PROOF_MODE: ProofMode = ProofMode::Core; +} + +impl ProofType for SphinxCompressedProof { + const PROOF_MODE: ProofMode = ProofMode::Compressed; +} + +impl ProofType for SphinxPlonkBn254Proof { + const PROOF_MODE: ProofMode = ProofMode::Plonk; +} diff --git a/sdk/src/provers/local.rs b/sdk/src/provers/local.rs index b9134c386..73f9b22c4 100644 --- a/sdk/src/provers/local.rs +++ b/sdk/src/provers/local.rs @@ -1,5 +1,4 @@ use anyhow::Result; -use cfg_if::cfg_if; use sphinx_prover::{SphinxProver, SphinxStdin}; use crate::{ @@ -41,6 +40,7 @@ impl Prover for LocalProver { proof: proof.proof.0, stdin: proof.stdin, public_values: proof.public_values, + sphinx_version: self.version().to_string(), }) } @@ -57,43 +57,39 @@ impl Prover for LocalProver { proof: reduce_proof.proof, stdin, public_values, + sphinx_version: self.version().to_string(), }) } - #[allow(unused)] fn prove_plonk( &self, pk: &SphinxProvingKey, stdin: SphinxStdin, ) -> Result { - cfg_if! { - if #[cfg(feature = "plonk")] { - - let proof = self.prover.prove_core(pk, &stdin)?; - let deferred_proofs = stdin.proofs.iter().map(|p| p.0.clone()).collect(); - let public_values = proof.public_values.clone(); - let reduce_proof = self.prover.compress(&pk.vk, proof, deferred_proofs)?; - let compress_proof = self.prover.shrink(reduce_proof)?; - let outer_proof = self.prover.wrap_bn254(compress_proof)?; + let proof = self.prover.prove_core(pk, &stdin)?; + let deferred_proofs = stdin.proofs.iter().map(|p| p.0.clone()).collect(); + let public_values = proof.public_values.clone(); + let reduce_proof = self.prover.compress(&pk.vk, proof, deferred_proofs)?; + let compress_proof = self.prover.shrink(reduce_proof)?; + let outer_proof = self.prover.wrap_bn254(compress_proof)?; - let plonk_bn254_aritfacts = if sphinx_prover::build::sphinx_dev_mode() { - sphinx_prover::build::try_build_plonk_bn254_artifacts_dev( - &self.prover.wrap_vk, - &outer_proof.proof, - ) - } else { - sphinx_prover::build::try_install_plonk_bn254_artifacts(false) - }; - let proof = self.prover.wrap_plonk_bn254(outer_proof, &plonk_bn254_aritfacts); - Ok(SphinxProofWithPublicValues { - proof, - stdin, - public_values, - }) - } else { - panic!("plonk feature not enabled") - } - } + let plonk_bn254_aritfacts = if sphinx_prover::build::sphinx_dev_mode() { + sphinx_prover::build::try_build_plonk_bn254_artifacts_dev( + &self.prover.wrap_vk, + &outer_proof.proof, + ) + } else { + sphinx_prover::build::try_install_plonk_bn254_artifacts(false) + }; + let proof = self + .prover + .wrap_plonk_bn254(outer_proof, &plonk_bn254_aritfacts); + Ok(SphinxProofWithPublicValues { + proof, + stdin, + public_values, + sphinx_version: self.version().to_string(), + }) } } diff --git a/sdk/src/provers/mock.rs b/sdk/src/provers/mock.rs index d413e214f..3e635c2df 100644 --- a/sdk/src/provers/mock.rs +++ b/sdk/src/provers/mock.rs @@ -1,8 +1,7 @@ #![allow(unused_variables)] use crate::{ - Prover, SphinxCompressedProof, SphinxPlonkBn254Proof, SphinxProof, - SphinxProofVerificationError, SphinxProofWithPublicValues, SphinxProvingKey, - SphinxVerifyingKey, + Prover, SphinxCompressedProof, SphinxPlonkBn254Proof, SphinxProof, SphinxProofWithPublicValues, + SphinxProvingKey, SphinxVerificationError, SphinxVerifyingKey, }; use anyhow::Result; use p3_field::PrimeField; @@ -45,6 +44,7 @@ impl Prover for MockProver { proof: vec![], stdin, public_values, + sphinx_version: self.version().to_string(), }) } @@ -70,9 +70,11 @@ impl Prover for MockProver { ], encoded_proof: "".to_string(), raw_proof: "".to_string(), + plonk_vkey_hash: [0; 32], }, stdin, public_values, + sphinx_version: self.version().to_string(), }) } @@ -80,7 +82,7 @@ impl Prover for MockProver { &self, _proof: &SphinxProof, _vkey: &SphinxVerifyingKey, - ) -> Result<(), SphinxProofVerificationError> { + ) -> Result<(), SphinxVerificationError> { Ok(()) } @@ -88,12 +90,17 @@ impl Prover for MockProver { &self, _proof: &SphinxCompressedProof, _vkey: &SphinxVerifyingKey, - ) -> Result<()> { + ) -> Result<(), SphinxVerificationError> { Ok(()) } - fn verify_plonk(&self, proof: &SphinxPlonkBn254Proof, vkey: &SphinxVerifyingKey) -> Result<()> { - verify_plonk_bn254_public_inputs(vkey, &proof.public_values, &proof.proof.public_inputs)?; + fn verify_plonk( + &self, + proof: &SphinxPlonkBn254Proof, + vkey: &SphinxVerifyingKey, + ) -> Result<(), SphinxVerificationError> { + verify_plonk_bn254_public_inputs(vkey, &proof.public_values, &proof.proof.public_inputs) + .map_err(SphinxVerificationError::Plonk)?; Ok(()) } } diff --git a/sdk/src/provers/mod.rs b/sdk/src/provers/mod.rs index a6660b9fc..c09ed5605 100644 --- a/sdk/src/provers/mod.rs +++ b/sdk/src/provers/mod.rs @@ -6,12 +6,15 @@ use anyhow::Result; pub use local::LocalProver; pub use mock::MockProver; use sphinx_core::stark::MachineVerificationError; -use sphinx_prover::types::SphinxCoreProofData; -use sphinx_prover::types::SphinxReduceProof; +use sphinx_core::SPHINX_CIRCUIT_VERSION; use sphinx_prover::CoreSC; +use sphinx_prover::InnerSC; +use sphinx_prover::SphinxCoreProofData; use sphinx_prover::SphinxProver; -use sphinx_prover::{types::SphinxProvingKey, types::SphinxVerifyingKey, SphinxStdin}; +use sphinx_prover::SphinxReduceProof; +use sphinx_prover::{SphinxProvingKey, SphinxStdin, SphinxVerifyingKey}; use strum_macros::EnumString; +use thiserror::Error; /// The type of prover. #[derive(Debug, PartialEq, Eq, EnumString)] @@ -21,12 +24,28 @@ pub enum ProverType { Network, } +#[derive(Error, Debug)] +pub enum SphinxVerificationError { + #[error("Version mismatch")] + VersionMismatch(String), + #[error("Core machine verification error: {0}")] + Core(MachineVerificationError), + #[error("Recursion verification error: {0}")] + Recursion(MachineVerificationError), + #[error("Plonk verification error: {0}")] + Plonk(anyhow::Error), +} + /// An implementation of [crate::ProverClient]. pub trait Prover: Send + Sync { fn id(&self) -> ProverType; fn sphinx_prover(&self) -> &SphinxProver; + fn version(&self) -> &str { + SPHINX_CIRCUIT_VERSION + } + fn setup(&self, elf: &[u8]) -> (SphinxProvingKey, SphinxVerifyingKey); /// Prove the execution of a RISCV ELF with the given inputs. @@ -51,9 +70,15 @@ pub trait Prover: Send + Sync { &self, proof: &SphinxProof, vkey: &SphinxVerifyingKey, - ) -> Result<(), MachineVerificationError> { + ) -> Result<(), SphinxVerificationError> { + if proof.sphinx_version != self.version() { + return Err(SphinxVerificationError::VersionMismatch( + proof.sphinx_version.clone(), + )); + } self.sphinx_prover() .verify(&SphinxCoreProofData(proof.proof.clone()), vkey) + .map_err(SphinxVerificationError::Core) } /// Verify that a compressed SP1 proof is valid given its vkey and metadata. @@ -61,7 +86,12 @@ pub trait Prover: Send + Sync { &self, proof: &SphinxCompressedProof, vkey: &SphinxVerifyingKey, - ) -> Result<()> { + ) -> Result<(), SphinxVerificationError> { + if proof.sphinx_version != self.version() { + return Err(SphinxVerificationError::VersionMismatch( + proof.sphinx_version.clone(), + )); + } self.sphinx_prover() .verify_compressed( &SphinxReduceProof { @@ -69,12 +99,21 @@ pub trait Prover: Send + Sync { }, vkey, ) - .map_err(|e| e.into()) + .map_err(SphinxVerificationError::Recursion) } /// Verify that a SP1 PLONK proof is valid. Verify that the public inputs of the PlonkBn254 proof match /// the hash of the VK and the committed public values of the SP1ProofWithPublicValues. - fn verify_plonk(&self, proof: &SphinxPlonkBn254Proof, vkey: &SphinxVerifyingKey) -> Result<()> { + fn verify_plonk( + &self, + proof: &SphinxPlonkBn254Proof, + vkey: &SphinxVerifyingKey, + ) -> Result<(), SphinxVerificationError> { + if proof.sphinx_version != self.version() { + return Err(SphinxVerificationError::VersionMismatch( + proof.sphinx_version.clone(), + )); + } let sphinx_prover = self.sphinx_prover(); let plonk_bn254_aritfacts = if sphinx_prover::build::sphinx_dev_mode() { @@ -82,12 +121,14 @@ pub trait Prover: Send + Sync { } else { sphinx_prover::build::try_install_plonk_bn254_artifacts(false) }; - sphinx_prover.verify_plonk_bn254( - &proof.proof, - vkey, - &proof.public_values, - &plonk_bn254_aritfacts, - )?; + sphinx_prover + .verify_plonk_bn254( + &proof.proof, + vkey, + &proof.public_values, + &plonk_bn254_aritfacts, + ) + .map_err(SphinxVerificationError::Plonk)?; Ok(()) } diff --git a/tests/bls12381-fp-add/Cargo.lock b/tests/bls12381-fp-add/Cargo.lock index 5ea30c62e..f36778816 100644 --- a/tests/bls12381-fp-add/Cargo.lock +++ b/tests/bls12381-fp-add/Cargo.lock @@ -265,6 +265,12 @@ dependencies = [ "signature", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.154" @@ -504,6 +510,7 @@ dependencies = [ "cfg-if", "getrandom", "k256", + "lazy_static", "once_cell", "rand", "sha2", diff --git a/tests/bls12381-fp-add/elf/riscv32im-succinct-zkvm-elf b/tests/bls12381-fp-add/elf/riscv32im-succinct-zkvm-elf index f062ad4a6..ca365154b 100755 Binary files a/tests/bls12381-fp-add/elf/riscv32im-succinct-zkvm-elf and b/tests/bls12381-fp-add/elf/riscv32im-succinct-zkvm-elf differ diff --git a/tests/bls12381-fp-mul/Cargo.lock b/tests/bls12381-fp-mul/Cargo.lock index a728c0945..19106d92c 100644 --- a/tests/bls12381-fp-mul/Cargo.lock +++ b/tests/bls12381-fp-mul/Cargo.lock @@ -265,6 +265,12 @@ dependencies = [ "signature", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.154" @@ -504,6 +510,7 @@ dependencies = [ "cfg-if", "getrandom", "k256", + "lazy_static", "once_cell", "rand", "sha2", diff --git a/tests/bls12381-fp-mul/elf/riscv32im-succinct-zkvm-elf b/tests/bls12381-fp-mul/elf/riscv32im-succinct-zkvm-elf index ebe7ce88f..909f63f0f 100755 Binary files a/tests/bls12381-fp-mul/elf/riscv32im-succinct-zkvm-elf and b/tests/bls12381-fp-mul/elf/riscv32im-succinct-zkvm-elf differ diff --git a/tests/bls12381-fp-sub/Cargo.lock b/tests/bls12381-fp-sub/Cargo.lock index 86806fb39..dd14d8307 100644 --- a/tests/bls12381-fp-sub/Cargo.lock +++ b/tests/bls12381-fp-sub/Cargo.lock @@ -265,6 +265,12 @@ dependencies = [ "signature", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.154" @@ -504,6 +510,7 @@ dependencies = [ "cfg-if", "getrandom", "k256", + "lazy_static", "once_cell", "rand", "sha2", diff --git a/tests/bls12381-fp-sub/elf/riscv32im-succinct-zkvm-elf b/tests/bls12381-fp-sub/elf/riscv32im-succinct-zkvm-elf index dbe3fa58d..928f1e267 100755 Binary files a/tests/bls12381-fp-sub/elf/riscv32im-succinct-zkvm-elf and b/tests/bls12381-fp-sub/elf/riscv32im-succinct-zkvm-elf differ diff --git a/tests/bls12381-fp2-add/Cargo.lock b/tests/bls12381-fp2-add/Cargo.lock index 4d5dbdddf..788e31f5a 100644 --- a/tests/bls12381-fp2-add/Cargo.lock +++ b/tests/bls12381-fp2-add/Cargo.lock @@ -68,7 +68,7 @@ dependencies = [ [[package]] name = "bls12_381" version = "0.8.0" -source = "git+https://github.com/lurk-lab/bls12_381.git?branch=zkvm#811d00a5b776b606cbcc091e82e7828bd5b5372c" +source = "git+https://github.com/lurk-lab/bls12_381.git?branch=zkvm#0d57d6ac0af6a464c4764809b5bf994d15920762" dependencies = [ "cfg-if", "ff", @@ -244,9 +244,9 @@ dependencies = [ [[package]] name = "hybrid-array" -version = "0.2.0-rc.8" +version = "0.2.0-rc.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53668f5da5a41d9eaf4bf7064be46d1ebe6a4e1ceed817f387587b18f2b51047" +checksum = "4d306b679262030ad8813a82d4915fc04efff97776e4db7f8eb5137039d56400" dependencies = [ "typenum", ] @@ -265,6 +265,12 @@ dependencies = [ "signature", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.155" @@ -365,9 +371,9 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.82" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] @@ -443,18 +449,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.203" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" +checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.203" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" +checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" dependencies = [ "proc-macro2", "quote", @@ -504,6 +510,7 @@ dependencies = [ "cfg-if", "getrandom", "k256", + "lazy_static", "once_cell", "rand", "sha2", @@ -522,15 +529,15 @@ dependencies = [ [[package]] name = "subtle" -version = "2.5.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.63" +version = "2.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704" +checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" dependencies = [ "proc-macro2", "quote", @@ -578,6 +585,6 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" diff --git a/tests/bls12381-fp2-add/elf/riscv32im-succinct-zkvm-elf b/tests/bls12381-fp2-add/elf/riscv32im-succinct-zkvm-elf index 0118320a3..e7049f5b9 100755 Binary files a/tests/bls12381-fp2-add/elf/riscv32im-succinct-zkvm-elf and b/tests/bls12381-fp2-add/elf/riscv32im-succinct-zkvm-elf differ diff --git a/tests/bls12381-fp2-mul/Cargo.lock b/tests/bls12381-fp2-mul/Cargo.lock index 496764ab2..0672d7634 100644 --- a/tests/bls12381-fp2-mul/Cargo.lock +++ b/tests/bls12381-fp2-mul/Cargo.lock @@ -265,6 +265,12 @@ dependencies = [ "signature", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.154" @@ -504,6 +510,7 @@ dependencies = [ "cfg-if", "getrandom", "k256", + "lazy_static", "once_cell", "rand", "sha2", diff --git a/tests/bls12381-fp2-mul/elf/riscv32im-succinct-zkvm-elf b/tests/bls12381-fp2-mul/elf/riscv32im-succinct-zkvm-elf index a16a8f0c7..b065482f3 100755 Binary files a/tests/bls12381-fp2-mul/elf/riscv32im-succinct-zkvm-elf and b/tests/bls12381-fp2-mul/elf/riscv32im-succinct-zkvm-elf differ diff --git a/tests/bls12381-fp2-sub/Cargo.lock b/tests/bls12381-fp2-sub/Cargo.lock index 0133bcd37..d82f005c8 100644 --- a/tests/bls12381-fp2-sub/Cargo.lock +++ b/tests/bls12381-fp2-sub/Cargo.lock @@ -68,7 +68,7 @@ dependencies = [ [[package]] name = "bls12_381" version = "0.8.0" -source = "git+https://github.com/lurk-lab/bls12_381.git?branch=zkvm#811d00a5b776b606cbcc091e82e7828bd5b5372c" +source = "git+https://github.com/lurk-lab/bls12_381.git?branch=zkvm#0d57d6ac0af6a464c4764809b5bf994d15920762" dependencies = [ "cfg-if", "ff", @@ -244,9 +244,9 @@ dependencies = [ [[package]] name = "hybrid-array" -version = "0.2.0-rc.8" +version = "0.2.0-rc.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53668f5da5a41d9eaf4bf7064be46d1ebe6a4e1ceed817f387587b18f2b51047" +checksum = "4d306b679262030ad8813a82d4915fc04efff97776e4db7f8eb5137039d56400" dependencies = [ "typenum", ] @@ -265,6 +265,12 @@ dependencies = [ "signature", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.155" @@ -365,9 +371,9 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.82" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] @@ -443,18 +449,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.203" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" +checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.203" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" +checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" dependencies = [ "proc-macro2", "quote", @@ -504,6 +510,7 @@ dependencies = [ "cfg-if", "getrandom", "k256", + "lazy_static", "once_cell", "rand", "sha2", @@ -522,15 +529,15 @@ dependencies = [ [[package]] name = "subtle" -version = "2.5.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.63" +version = "2.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704" +checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" dependencies = [ "proc-macro2", "quote", @@ -578,6 +585,6 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" diff --git a/tests/bls12381-fp2-sub/elf/riscv32im-succinct-zkvm-elf b/tests/bls12381-fp2-sub/elf/riscv32im-succinct-zkvm-elf index 27b542092..d201c5f87 100755 Binary files a/tests/bls12381-fp2-sub/elf/riscv32im-succinct-zkvm-elf and b/tests/bls12381-fp2-sub/elf/riscv32im-succinct-zkvm-elf differ diff --git a/tests/bls12381-g1-add/Cargo.lock b/tests/bls12381-g1-add/Cargo.lock index 14dd33b46..1c86ed957 100644 --- a/tests/bls12381-g1-add/Cargo.lock +++ b/tests/bls12381-g1-add/Cargo.lock @@ -258,6 +258,12 @@ dependencies = [ "signature", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.154" @@ -497,6 +503,7 @@ dependencies = [ "cfg-if", "getrandom", "k256", + "lazy_static", "once_cell", "rand", "sha2", diff --git a/tests/bls12381-g1-add/elf/riscv32im-succinct-zkvm-elf b/tests/bls12381-g1-add/elf/riscv32im-succinct-zkvm-elf index 04f4411a6..76f1eff4a 100755 Binary files a/tests/bls12381-g1-add/elf/riscv32im-succinct-zkvm-elf and b/tests/bls12381-g1-add/elf/riscv32im-succinct-zkvm-elf differ diff --git a/tests/bls12381-g1-decompress/Cargo.lock b/tests/bls12381-g1-decompress/Cargo.lock index d4398e02a..28390980e 100644 --- a/tests/bls12381-g1-decompress/Cargo.lock +++ b/tests/bls12381-g1-decompress/Cargo.lock @@ -251,6 +251,12 @@ dependencies = [ "signature", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.154" @@ -429,6 +435,7 @@ dependencies = [ "cfg-if", "getrandom", "k256", + "lazy_static", "once_cell", "rand", "sha2", diff --git a/tests/bls12381-g1-decompress/elf/riscv32im-succinct-zkvm-elf b/tests/bls12381-g1-decompress/elf/riscv32im-succinct-zkvm-elf index 1b1a40267..ad70e8f92 100755 Binary files a/tests/bls12381-g1-decompress/elf/riscv32im-succinct-zkvm-elf and b/tests/bls12381-g1-decompress/elf/riscv32im-succinct-zkvm-elf differ diff --git a/tests/bls12381-g1-double/Cargo.lock b/tests/bls12381-g1-double/Cargo.lock index 409f23ec9..d021f36e9 100644 --- a/tests/bls12381-g1-double/Cargo.lock +++ b/tests/bls12381-g1-double/Cargo.lock @@ -258,6 +258,12 @@ dependencies = [ "signature", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.155" @@ -497,6 +503,7 @@ dependencies = [ "cfg-if", "getrandom", "k256", + "lazy_static", "once_cell", "rand", "sha2", diff --git a/tests/bls12381-g1-double/elf/riscv32im-succinct-zkvm-elf b/tests/bls12381-g1-double/elf/riscv32im-succinct-zkvm-elf index fe48c9721..f8ed3d985 100755 Binary files a/tests/bls12381-g1-double/elf/riscv32im-succinct-zkvm-elf and b/tests/bls12381-g1-double/elf/riscv32im-succinct-zkvm-elf differ diff --git a/tests/bls12381-g1-scalarmul/Cargo.lock b/tests/bls12381-g1-scalarmul/Cargo.lock index c823746dc..29e644645 100644 --- a/tests/bls12381-g1-scalarmul/Cargo.lock +++ b/tests/bls12381-g1-scalarmul/Cargo.lock @@ -253,6 +253,12 @@ dependencies = [ "signature", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.154" @@ -440,6 +446,7 @@ dependencies = [ "cfg-if", "getrandom", "k256", + "lazy_static", "once_cell", "rand", "sha2", diff --git a/tests/bls12381-g1-scalarmul/elf/riscv32im-succinct-zkvm-elf b/tests/bls12381-g1-scalarmul/elf/riscv32im-succinct-zkvm-elf index c3867656d..44a669f90 100755 Binary files a/tests/bls12381-g1-scalarmul/elf/riscv32im-succinct-zkvm-elf and b/tests/bls12381-g1-scalarmul/elf/riscv32im-succinct-zkvm-elf differ diff --git a/tests/bls12381-g2-add/Cargo.lock b/tests/bls12381-g2-add/Cargo.lock index 1b16dfc85..2accba1ab 100644 --- a/tests/bls12381-g2-add/Cargo.lock +++ b/tests/bls12381-g2-add/Cargo.lock @@ -251,6 +251,12 @@ dependencies = [ "signature", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.154" @@ -429,6 +435,7 @@ dependencies = [ "cfg-if", "getrandom", "k256", + "lazy_static", "once_cell", "rand", "sha2", diff --git a/tests/bls12381-g2-add/elf/riscv32im-succinct-zkvm-elf b/tests/bls12381-g2-add/elf/riscv32im-succinct-zkvm-elf index 17ae22f2f..20c2bd8ad 100755 Binary files a/tests/bls12381-g2-add/elf/riscv32im-succinct-zkvm-elf and b/tests/bls12381-g2-add/elf/riscv32im-succinct-zkvm-elf differ diff --git a/tests/bls12381-g2-double/Cargo.lock b/tests/bls12381-g2-double/Cargo.lock index e73452d15..ea80b3119 100644 --- a/tests/bls12381-g2-double/Cargo.lock +++ b/tests/bls12381-g2-double/Cargo.lock @@ -251,6 +251,12 @@ dependencies = [ "signature", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.155" @@ -429,6 +435,7 @@ dependencies = [ "cfg-if", "getrandom", "k256", + "lazy_static", "once_cell", "rand", "sha2", diff --git a/tests/bls12381-g2-double/elf/riscv32im-succinct-zkvm-elf b/tests/bls12381-g2-double/elf/riscv32im-succinct-zkvm-elf index 4e67df441..328b04060 100755 Binary files a/tests/bls12381-g2-double/elf/riscv32im-succinct-zkvm-elf and b/tests/bls12381-g2-double/elf/riscv32im-succinct-zkvm-elf differ diff --git a/tests/bn254-add/Cargo.lock b/tests/bn254-add/Cargo.lock index c6d858942..27a2d2114 100644 --- a/tests/bn254-add/Cargo.lock +++ b/tests/bn254-add/Cargo.lock @@ -258,6 +258,12 @@ dependencies = [ "signature", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.155" @@ -497,6 +503,7 @@ dependencies = [ "cfg-if", "getrandom", "k256", + "lazy_static", "once_cell", "rand", "sha2", diff --git a/tests/bn254-add/elf/riscv32im-succinct-zkvm-elf b/tests/bn254-add/elf/riscv32im-succinct-zkvm-elf index 9e605aae1..acb1b7c20 100755 Binary files a/tests/bn254-add/elf/riscv32im-succinct-zkvm-elf and b/tests/bn254-add/elf/riscv32im-succinct-zkvm-elf differ diff --git a/tests/bn254-double/Cargo.lock b/tests/bn254-double/Cargo.lock index 0b1a74a2d..37ef4ba16 100644 --- a/tests/bn254-double/Cargo.lock +++ b/tests/bn254-double/Cargo.lock @@ -265,6 +265,12 @@ dependencies = [ "signature", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.155" @@ -504,6 +510,7 @@ dependencies = [ "cfg-if", "getrandom", "k256", + "lazy_static", "once_cell", "rand", "sha2", diff --git a/tests/bn254-double/elf/riscv32im-succinct-zkvm-elf b/tests/bn254-double/elf/riscv32im-succinct-zkvm-elf index 6ad0d4f81..e1352e1d0 100755 Binary files a/tests/bn254-double/elf/riscv32im-succinct-zkvm-elf and b/tests/bn254-double/elf/riscv32im-succinct-zkvm-elf differ diff --git a/tests/bn254-mul/Cargo.lock b/tests/bn254-mul/Cargo.lock index 8dca820ab..c4b4d2d0b 100644 --- a/tests/bn254-mul/Cargo.lock +++ b/tests/bn254-mul/Cargo.lock @@ -253,6 +253,12 @@ dependencies = [ "signature", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.155" @@ -440,6 +446,7 @@ dependencies = [ "cfg-if", "getrandom", "k256", + "lazy_static", "once_cell", "rand", "sha2", diff --git a/tests/bn254-mul/elf/riscv32im-succinct-zkvm-elf b/tests/bn254-mul/elf/riscv32im-succinct-zkvm-elf index 1bcf651a9..cb71b81fb 100755 Binary files a/tests/bn254-mul/elf/riscv32im-succinct-zkvm-elf and b/tests/bn254-mul/elf/riscv32im-succinct-zkvm-elf differ diff --git a/tests/cycle-tracker/Cargo.lock b/tests/cycle-tracker/Cargo.lock index dd4b04387..daafb118d 100644 --- a/tests/cycle-tracker/Cargo.lock +++ b/tests/cycle-tracker/Cargo.lock @@ -252,6 +252,12 @@ dependencies = [ "signature", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.155" @@ -439,6 +445,7 @@ dependencies = [ "cfg-if", "getrandom", "k256", + "lazy_static", "once_cell", "rand", "sha2", diff --git a/tests/cycle-tracker/elf/riscv32im-succinct-zkvm-elf b/tests/cycle-tracker/elf/riscv32im-succinct-zkvm-elf index 5a6365667..24eead8cf 100755 Binary files a/tests/cycle-tracker/elf/riscv32im-succinct-zkvm-elf and b/tests/cycle-tracker/elf/riscv32im-succinct-zkvm-elf differ diff --git a/tests/ecrecover/Cargo.lock b/tests/ecrecover/Cargo.lock index cf9a2f6da..597524fe0 100644 --- a/tests/ecrecover/Cargo.lock +++ b/tests/ecrecover/Cargo.lock @@ -266,6 +266,12 @@ dependencies = [ "signature", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.155" @@ -505,6 +511,7 @@ dependencies = [ "cfg-if", "getrandom", "k256", + "lazy_static", "once_cell", "rand", "sha2", diff --git a/tests/ecrecover/elf/riscv32im-succinct-zkvm-elf b/tests/ecrecover/elf/riscv32im-succinct-zkvm-elf index 499be1340..2cfe51144 100755 Binary files a/tests/ecrecover/elf/riscv32im-succinct-zkvm-elf and b/tests/ecrecover/elf/riscv32im-succinct-zkvm-elf differ diff --git a/tests/ed-add/Cargo.lock b/tests/ed-add/Cargo.lock index f598433f2..2589b7f0b 100644 --- a/tests/ed-add/Cargo.lock +++ b/tests/ed-add/Cargo.lock @@ -265,6 +265,12 @@ dependencies = [ "signature", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.155" @@ -504,6 +510,7 @@ dependencies = [ "cfg-if", "getrandom", "k256", + "lazy_static", "once_cell", "rand", "sha2", diff --git a/tests/ed-add/elf/riscv32im-succinct-zkvm-elf b/tests/ed-add/elf/riscv32im-succinct-zkvm-elf index 0376bb678..9e1253904 100755 Binary files a/tests/ed-add/elf/riscv32im-succinct-zkvm-elf and b/tests/ed-add/elf/riscv32im-succinct-zkvm-elf differ diff --git a/tests/ed-decompress/Cargo.lock b/tests/ed-decompress/Cargo.lock index 60386fd79..c0fd8cfb2 100644 --- a/tests/ed-decompress/Cargo.lock +++ b/tests/ed-decompress/Cargo.lock @@ -258,6 +258,12 @@ dependencies = [ "signature", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.155" @@ -436,6 +442,7 @@ dependencies = [ "cfg-if", "getrandom", "k256", + "lazy_static", "once_cell", "rand", "sha2", diff --git a/tests/ed-decompress/elf/riscv32im-succinct-zkvm-elf b/tests/ed-decompress/elf/riscv32im-succinct-zkvm-elf index 6cd453f94..523c37cb6 100755 Binary files a/tests/ed-decompress/elf/riscv32im-succinct-zkvm-elf and b/tests/ed-decompress/elf/riscv32im-succinct-zkvm-elf differ diff --git a/tests/ed25519/Cargo.lock b/tests/ed25519/Cargo.lock index 940882a06..910a85b39 100644 --- a/tests/ed25519/Cargo.lock +++ b/tests/ed25519/Cargo.lock @@ -314,6 +314,12 @@ dependencies = [ "signature", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.155" @@ -513,6 +519,7 @@ dependencies = [ "cfg-if", "getrandom", "k256", + "lazy_static", "once_cell", "rand", "sha2", diff --git a/tests/ed25519/elf/riscv32im-succinct-zkvm-elf b/tests/ed25519/elf/riscv32im-succinct-zkvm-elf index 693bd5b70..3f04db1df 100755 Binary files a/tests/ed25519/elf/riscv32im-succinct-zkvm-elf and b/tests/ed25519/elf/riscv32im-succinct-zkvm-elf differ diff --git a/tests/fibonacci/Cargo.lock b/tests/fibonacci/Cargo.lock index 6bcdfbecc..096c42278 100644 --- a/tests/fibonacci/Cargo.lock +++ b/tests/fibonacci/Cargo.lock @@ -251,6 +251,12 @@ dependencies = [ "signature", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.155" @@ -429,6 +435,7 @@ dependencies = [ "cfg-if", "getrandom", "k256", + "lazy_static", "once_cell", "rand", "sha2", diff --git a/tests/fibonacci/elf/riscv32im-succinct-zkvm-elf b/tests/fibonacci/elf/riscv32im-succinct-zkvm-elf index 4deb2aac8..296e41e3f 100755 Binary files a/tests/fibonacci/elf/riscv32im-succinct-zkvm-elf and b/tests/fibonacci/elf/riscv32im-succinct-zkvm-elf differ diff --git a/tests/hint-io/Cargo.lock b/tests/hint-io/Cargo.lock index 775c2d901..1a0d6bce7 100644 --- a/tests/hint-io/Cargo.lock +++ b/tests/hint-io/Cargo.lock @@ -251,6 +251,12 @@ dependencies = [ "signature", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.155" @@ -429,6 +435,7 @@ dependencies = [ "cfg-if", "getrandom", "k256", + "lazy_static", "once_cell", "rand", "sha2", diff --git a/tests/hint-io/elf/riscv32im-succinct-zkvm-elf b/tests/hint-io/elf/riscv32im-succinct-zkvm-elf index 3e2cfae19..7881f30a7 100755 Binary files a/tests/hint-io/elf/riscv32im-succinct-zkvm-elf and b/tests/hint-io/elf/riscv32im-succinct-zkvm-elf differ diff --git a/tests/keccak-permute/Cargo.lock b/tests/keccak-permute/Cargo.lock index c158db228..db8e70d95 100644 --- a/tests/keccak-permute/Cargo.lock +++ b/tests/keccak-permute/Cargo.lock @@ -251,6 +251,12 @@ dependencies = [ "sphinx-zkvm", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.155" @@ -429,6 +435,7 @@ dependencies = [ "cfg-if", "getrandom", "k256", + "lazy_static", "once_cell", "rand", "sha2", diff --git a/tests/keccak-permute/elf/riscv32im-succinct-zkvm-elf b/tests/keccak-permute/elf/riscv32im-succinct-zkvm-elf index dbbf186cb..f92cf8602 100755 Binary files a/tests/keccak-permute/elf/riscv32im-succinct-zkvm-elf and b/tests/keccak-permute/elf/riscv32im-succinct-zkvm-elf differ diff --git a/tests/keccak256/Cargo.lock b/tests/keccak256/Cargo.lock index ae1caba53..4da0b5e30 100644 --- a/tests/keccak256/Cargo.lock +++ b/tests/keccak256/Cargo.lock @@ -258,6 +258,12 @@ dependencies = [ "tiny-keccak", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.155" @@ -436,6 +442,7 @@ dependencies = [ "cfg-if", "getrandom", "k256", + "lazy_static", "once_cell", "rand", "sha2", diff --git a/tests/keccak256/elf/riscv32im-succinct-zkvm-elf b/tests/keccak256/elf/riscv32im-succinct-zkvm-elf index 38ac9ebfa..6e26896fe 100755 Binary files a/tests/keccak256/elf/riscv32im-succinct-zkvm-elf and b/tests/keccak256/elf/riscv32im-succinct-zkvm-elf differ diff --git a/tests/panic/Cargo.lock b/tests/panic/Cargo.lock index 16344fd0c..04ab481ea 100644 --- a/tests/panic/Cargo.lock +++ b/tests/panic/Cargo.lock @@ -244,6 +244,12 @@ dependencies = [ "signature", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.154" @@ -439,6 +445,7 @@ dependencies = [ "cfg-if", "getrandom", "k256", + "lazy_static", "once_cell", "rand", "sha2", diff --git a/tests/panic/elf/riscv32im-succinct-zkvm-elf b/tests/panic/elf/riscv32im-succinct-zkvm-elf index a233d72bd..ee7d1fa23 100755 Binary files a/tests/panic/elf/riscv32im-succinct-zkvm-elf and b/tests/panic/elf/riscv32im-succinct-zkvm-elf differ diff --git a/tests/rand/Cargo.lock b/tests/rand/Cargo.lock new file mode 100644 index 000000000..be7744cdd --- /dev/null +++ b/tests/rand/Cargo.lock @@ -0,0 +1,537 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "anyhow" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bls12_381" +version = "0.8.0" +source = "git+https://github.com/lurk-lab/bls12_381.git?branch=zkvm#0d57d6ac0af6a464c4764809b5bf994d15920762" +dependencies = [ + "cfg-if", + "ff", + "group", + "pairing", + "rand_core", + "subtle", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "der" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest", + "elliptic-curve", + "rfc6979", + "signature", + "spki", +] + +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest", + "ff", + "generic-array", + "group", + "pkcs8", + "rand_core", + "sec1", + "subtle", + "tap", + "zeroize", +] + +[[package]] +name = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "bitvec", + "rand_core", + "subtle", +] + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", + "zeroize", +] + +[[package]] +name = "getrandom" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core", + "subtle", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "hybrid-array" +version = "0.2.0-rc.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d306b679262030ad8813a82d4915fc04efff97776e4db7f8eb5137039d56400" +dependencies = [ + "typenum", +] + +[[package]] +name = "k256" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "once_cell", + "sha2", + "signature", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.155" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "pairing" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fec4625e73cf41ef4bb6846cafa6d44736525f442ba45e407c4a000a13996f" +dependencies = [ + "group", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand-test" +version = "1.0.0-rc.1" +dependencies = [ + "rand", + "sphinx-derive", + "sphinx-zkvm", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + +[[package]] +name = "serde" +version = "1.0.204" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.204" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.72", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest", + "rand_core", +] + +[[package]] +name = "sphinx-derive" +version = "1.0.0" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "sphinx-precompiles" +version = "1.0.0" +dependencies = [ + "anyhow", + "bincode", + "bls12_381", + "cfg-if", + "getrandom", + "hybrid-array", + "k256", + "serde", +] + +[[package]] +name = "sphinx-zkvm" +version = "1.0.0" +dependencies = [ + "bincode", + "cfg-if", + "getrandom", + "k256", + "lazy_static", + "once_cell", + "rand", + "sha2", + "sphinx-precompiles", +] + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" diff --git a/tests/rand/Cargo.toml b/tests/rand/Cargo.toml new file mode 100644 index 000000000..c23a5d7ce --- /dev/null +++ b/tests/rand/Cargo.toml @@ -0,0 +1,11 @@ +[workspace] +[package] +name = "rand-test" +version = "1.0.0-rc.1" +edition = "2021" +publish = false + +[dependencies] +sphinx-zkvm = { path = "../../zkvm/entrypoint" } +sphinx-derive = { path = "../../derive" } +rand = "0.8.5" \ No newline at end of file diff --git a/tests/rand/elf/riscv32im-succinct-zkvm-elf b/tests/rand/elf/riscv32im-succinct-zkvm-elf new file mode 100755 index 000000000..b7c35df9e Binary files /dev/null and b/tests/rand/elf/riscv32im-succinct-zkvm-elf differ diff --git a/tests/rand/src/main.rs b/tests/rand/src/main.rs new file mode 100644 index 000000000..67770b495 --- /dev/null +++ b/tests/rand/src/main.rs @@ -0,0 +1,12 @@ +#![no_main] +sphinx_zkvm::entrypoint!(main); + +use rand::Rng; + +pub fn main() { + let mut rng = rand::thread_rng(); + for _ in 0..16 { + let num = rng.gen::(); + println!("{num}"); + } +} diff --git a/tests/secp256k1-add/Cargo.lock b/tests/secp256k1-add/Cargo.lock index 1e48d4b1e..6607ffdfc 100644 --- a/tests/secp256k1-add/Cargo.lock +++ b/tests/secp256k1-add/Cargo.lock @@ -256,6 +256,12 @@ dependencies = [ "signature", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.155" @@ -504,6 +510,7 @@ dependencies = [ "cfg-if", "getrandom", "k256", + "lazy_static", "once_cell", "rand", "sha2", diff --git a/tests/secp256k1-add/elf/riscv32im-succinct-zkvm-elf b/tests/secp256k1-add/elf/riscv32im-succinct-zkvm-elf index aea6ca9fa..756b56547 100755 Binary files a/tests/secp256k1-add/elf/riscv32im-succinct-zkvm-elf and b/tests/secp256k1-add/elf/riscv32im-succinct-zkvm-elf differ diff --git a/tests/secp256k1-decompress/Cargo.lock b/tests/secp256k1-decompress/Cargo.lock index 34a5923ee..95b3bcaa5 100644 --- a/tests/secp256k1-decompress/Cargo.lock +++ b/tests/secp256k1-decompress/Cargo.lock @@ -244,6 +244,12 @@ dependencies = [ "signature", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.155" @@ -429,6 +435,7 @@ dependencies = [ "cfg-if", "getrandom", "k256", + "lazy_static", "once_cell", "rand", "sha2", diff --git a/tests/secp256k1-decompress/elf/riscv32im-succinct-zkvm-elf b/tests/secp256k1-decompress/elf/riscv32im-succinct-zkvm-elf index 6ff3d4cab..f3296be85 100755 Binary files a/tests/secp256k1-decompress/elf/riscv32im-succinct-zkvm-elf and b/tests/secp256k1-decompress/elf/riscv32im-succinct-zkvm-elf differ diff --git a/tests/secp256k1-double/Cargo.lock b/tests/secp256k1-double/Cargo.lock index cc2d5a6cc..bac5c10e0 100644 --- a/tests/secp256k1-double/Cargo.lock +++ b/tests/secp256k1-double/Cargo.lock @@ -256,6 +256,12 @@ dependencies = [ "signature", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.155" @@ -504,6 +510,7 @@ dependencies = [ "cfg-if", "getrandom", "k256", + "lazy_static", "once_cell", "rand", "sha2", diff --git a/tests/secp256k1-double/elf/riscv32im-succinct-zkvm-elf b/tests/secp256k1-double/elf/riscv32im-succinct-zkvm-elf index efecb758f..0c30f8109 100755 Binary files a/tests/secp256k1-double/elf/riscv32im-succinct-zkvm-elf and b/tests/secp256k1-double/elf/riscv32im-succinct-zkvm-elf differ diff --git a/tests/secp256k1-mul/Cargo.lock b/tests/secp256k1-mul/Cargo.lock index 9c3d596ed..b5aa19deb 100644 --- a/tests/secp256k1-mul/Cargo.lock +++ b/tests/secp256k1-mul/Cargo.lock @@ -244,6 +244,12 @@ dependencies = [ "signature", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.155" @@ -440,6 +446,7 @@ dependencies = [ "cfg-if", "getrandom", "k256", + "lazy_static", "once_cell", "rand", "sha2", diff --git a/tests/secp256k1-mul/elf/riscv32im-succinct-zkvm-elf b/tests/secp256k1-mul/elf/riscv32im-succinct-zkvm-elf index 6810c3f6e..db312b2ac 100755 Binary files a/tests/secp256k1-mul/elf/riscv32im-succinct-zkvm-elf and b/tests/secp256k1-mul/elf/riscv32im-succinct-zkvm-elf differ diff --git a/tests/sha-compress/Cargo.lock b/tests/sha-compress/Cargo.lock index 326bbb529..2c030a9fc 100644 --- a/tests/sha-compress/Cargo.lock +++ b/tests/sha-compress/Cargo.lock @@ -244,6 +244,12 @@ dependencies = [ "signature", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.155" @@ -429,6 +435,7 @@ dependencies = [ "cfg-if", "getrandom", "k256", + "lazy_static", "once_cell", "rand", "sha2", diff --git a/tests/sha-compress/elf/riscv32im-succinct-zkvm-elf b/tests/sha-compress/elf/riscv32im-succinct-zkvm-elf index 38fe112ba..c9699cb3b 100755 Binary files a/tests/sha-compress/elf/riscv32im-succinct-zkvm-elf and b/tests/sha-compress/elf/riscv32im-succinct-zkvm-elf differ diff --git a/tests/sha-extend/Cargo.lock b/tests/sha-extend/Cargo.lock index b182acf97..e2f0948fb 100644 --- a/tests/sha-extend/Cargo.lock +++ b/tests/sha-extend/Cargo.lock @@ -244,6 +244,12 @@ dependencies = [ "signature", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.155" @@ -429,6 +435,7 @@ dependencies = [ "cfg-if", "getrandom", "k256", + "lazy_static", "once_cell", "rand", "sha2", diff --git a/tests/sha-extend/elf/riscv32im-succinct-zkvm-elf b/tests/sha-extend/elf/riscv32im-succinct-zkvm-elf index 0367a0642..4458f5edc 100755 Binary files a/tests/sha-extend/elf/riscv32im-succinct-zkvm-elf and b/tests/sha-extend/elf/riscv32im-succinct-zkvm-elf differ diff --git a/tests/sha2/Cargo.lock b/tests/sha2/Cargo.lock index 2bbcffd31..42ea6759c 100644 --- a/tests/sha2/Cargo.lock +++ b/tests/sha2/Cargo.lock @@ -256,6 +256,12 @@ dependencies = [ "signature", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.155" @@ -454,6 +460,7 @@ dependencies = [ "cfg-if", "getrandom", "k256", + "lazy_static", "once_cell", "rand", "sha2 0.10.8", diff --git a/tests/sha2/elf/riscv32im-succinct-zkvm-elf b/tests/sha2/elf/riscv32im-succinct-zkvm-elf index 0cbad4334..dc0c2fead 100755 Binary files a/tests/sha2/elf/riscv32im-succinct-zkvm-elf and b/tests/sha2/elf/riscv32im-succinct-zkvm-elf differ diff --git a/tests/tendermint-benchmark/Cargo.lock b/tests/tendermint-benchmark/Cargo.lock index 3134f8099..a3c93a0df 100644 --- a/tests/tendermint-benchmark/Cargo.lock +++ b/tests/tendermint-benchmark/Cargo.lock @@ -434,6 +434,12 @@ dependencies = [ "signature", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.155" @@ -749,6 +755,7 @@ dependencies = [ "cfg-if", "getrandom", "k256", + "lazy_static", "once_cell", "rand", "sha2 0.10.8", diff --git a/tests/tendermint-benchmark/elf/riscv32im-succinct-zkvm-elf b/tests/tendermint-benchmark/elf/riscv32im-succinct-zkvm-elf index 0fde537cf..d79760b5c 100755 Binary files a/tests/tendermint-benchmark/elf/riscv32im-succinct-zkvm-elf and b/tests/tendermint-benchmark/elf/riscv32im-succinct-zkvm-elf differ diff --git a/tests/verify-proof/Cargo.lock b/tests/verify-proof/Cargo.lock index 27ced2308..f7352b4e5 100644 --- a/tests/verify-proof/Cargo.lock +++ b/tests/verify-proof/Cargo.lock @@ -615,6 +615,7 @@ dependencies = [ "cfg-if", "getrandom", "k256", + "lazy_static", "once_cell", "p3-baby-bear", "p3-field", diff --git a/tests/verify-proof/elf/riscv32im-succinct-zkvm-elf b/tests/verify-proof/elf/riscv32im-succinct-zkvm-elf index 15a08e33d..c0ee43052 100755 Binary files a/tests/verify-proof/elf/riscv32im-succinct-zkvm-elf and b/tests/verify-proof/elf/riscv32im-succinct-zkvm-elf differ diff --git a/zkvm/entrypoint/Cargo.toml b/zkvm/entrypoint/Cargo.toml index dfcbdf567..ef3e6c43f 100644 --- a/zkvm/entrypoint/Cargo.toml +++ b/zkvm/entrypoint/Cargo.toml @@ -13,13 +13,16 @@ p3-field = { workspace = true, optional = true } bincode = { workspace = true } cfg-if = { workspace = true } getrandom = { workspace = true, features = ["custom"] } +libm = { workspace = true, optional = true } k256 = { workspace = true, features = ["ecdsa", "std", "bits"] } +lazy_static = { workspace = true } once_cell = { workspace = true } rand = { workspace = true } sha2 = { workspace = true } [features] -default = [] +default = ["libm"] +libm = ["dep:libm"] verify = ["dep:sphinx-primitives", "dep:p3-baby-bear", "dep:p3-field", "sphinx-precompiles/verify"] diff --git a/zkvm/entrypoint/src/lib.rs b/zkvm/entrypoint/src/lib.rs index f2f91830a..a2e59309a 100644 --- a/zkvm/entrypoint/src/lib.rs +++ b/zkvm/entrypoint/src/lib.rs @@ -91,23 +91,16 @@ mod zkvm { .option pop; la sp, {0} lw sp, 0(sp) - jal ra, __start; + call __start; "#, sym STACK_TOP ); - static GETRANDOM_WARNING_ONCE: std::sync::Once = std::sync::Once::new(); - fn zkvm_getrandom(s: &mut [u8]) -> Result<(), Error> { - use rand::{Rng, SeedableRng}; - - GETRANDOM_WARNING_ONCE.call_once(|| { - println!("WARNING: Using insecure random number generator"); - }); - let mut rng = rand::rngs::StdRng::seed_from_u64(123); - for i in 0..s.len() { - s[i] = rng.gen(); + unsafe { + crate::syscalls::sys_rand(s.as_mut_ptr(), s.len()); } + Ok(()) } diff --git a/zkvm/entrypoint/src/syscalls/bigint.rs b/zkvm/entrypoint/src/syscalls/bigint.rs new file mode 100644 index 000000000..81b20ef4d --- /dev/null +++ b/zkvm/entrypoint/src/syscalls/bigint.rs @@ -0,0 +1,42 @@ +use sphinx_precompiles::BIGINT_WIDTH_WORDS; + +use super::syscall_uint256_mulmod; + +/// Sets result to be (x op y) % modulus. Currently only multiplication is supported. If modulus is +/// zero, the modulus applied is 2^256. +#[allow(unused_variables)] +#[no_mangle] +pub extern "C" fn sys_bigint( + result: *mut [u32; BIGINT_WIDTH_WORDS], + op: u32, + x: *const [u32; BIGINT_WIDTH_WORDS], + y: *const [u32; BIGINT_WIDTH_WORDS], + modulus: *const [u32; BIGINT_WIDTH_WORDS], +) { + // Instantiate a new uninitialized array of words to place the concatenated y and modulus. + let mut concat_y_modulus = core::mem::MaybeUninit::<[u32; BIGINT_WIDTH_WORDS * 2]>::uninit(); + unsafe { + let result_ptr = result as *mut u32; + let x_ptr = x as *const u32; + let y_ptr = y as *const u32; + let concat_ptr = concat_y_modulus.as_mut_ptr() as *mut u32; + + // First copy the y value into the concatenated array. + core::ptr::copy(y_ptr, concat_ptr, BIGINT_WIDTH_WORDS); + + // Then, copy the modulus value into the concatenated array. Add the width of the y value + // to the pointer to place the modulus value after the y value. + core::ptr::copy( + modulus as *const u32, + concat_ptr.add(BIGINT_WIDTH_WORDS), + BIGINT_WIDTH_WORDS, + ); + + // Copy x into the result array, as our syscall will write the result into the first input. + core::ptr::copy(x as *const u32, result_ptr, BIGINT_WIDTH_WORDS); + + // Call the uint256_mul syscall to multiply the x value with the concatenated y and modulus. + // This syscall writes the result in-place, so it will mutate the result ptr appropriately. + syscall_uint256_mulmod(result_ptr, concat_ptr); + } +} diff --git a/zkvm/entrypoint/src/syscalls/blake3_compress.rs b/zkvm/entrypoint/src/syscalls/blake3_compress.rs deleted file mode 100644 index 163421bf9..000000000 --- a/zkvm/entrypoint/src/syscalls/blake3_compress.rs +++ /dev/null @@ -1,22 +0,0 @@ -#[cfg(target_os = "zkvm")] -use core::arch::asm; - -/// Blake3 compress operation. -/// -/// The result is written over the input state. -#[allow(unused_variables)] -#[no_mangle] -pub(crate) extern "C" fn syscall_blake3_compress_inner(state: *mut u32, message: *mut u32) { - #[cfg(target_os = "zkvm")] - unsafe { - asm!( - "ecall", - in("t0") crate::syscalls::BLAKE3_COMPRESS_INNER, - in("a0") state, - in("a1") message - ); - } - - #[cfg(not(target_os = "zkvm"))] - unreachable!() -} diff --git a/zkvm/entrypoint/src/syscalls/mod.rs b/zkvm/entrypoint/src/syscalls/mod.rs index b21a59f2b..206f68c97 100644 --- a/zkvm/entrypoint/src/syscalls/mod.rs +++ b/zkvm/entrypoint/src/syscalls/mod.rs @@ -1,4 +1,3 @@ -mod blake3_compress; mod bls12_381; mod bn254; mod ed25519; @@ -68,9 +67,6 @@ pub const SECP256K1_DOUBLE: u32 = 0x00_00_01_0B; /// Executes `K256_DECOMPRESS`. pub const SECP256K1_DECOMPRESS: u32 = 0x00_00_01_0C; -/// Executes `BLAKE3_COMPRESS_INNER`. -pub const BLAKE3_COMPRESS_INNER: u32 = 0x00_38_01_0D; - /// Executes `BN254_ADD`. pub const BN254_ADD: u32 = 0x00_01_01_0E; diff --git a/zkvm/entrypoint/src/syscalls/sys.rs b/zkvm/entrypoint/src/syscalls/sys.rs index 2a62372a6..520d58ef9 100644 --- a/zkvm/entrypoint/src/syscalls/sys.rs +++ b/zkvm/entrypoint/src/syscalls/sys.rs @@ -1,5 +1,40 @@ +use std::sync::Mutex; + +use lazy_static::lazy_static; +use rand::{rngs::StdRng, Rng, SeedableRng}; + use crate::syscalls::{syscall_halt, syscall_write}; +/// The random number generator seed for the zkVM. +/// +/// In the future, we can pass in this seed from the host or have the verifier generate it. +const PRNG_SEED: u64 = 0x123456789abcdef0; + +lazy_static! { + /// A lazy static to generate a global random number generator. + static ref RNG: Mutex = Mutex::new(StdRng::seed_from_u64(PRNG_SEED)); +} + +/// A lazy static to print a warning once for using the `sys_rand` system call. +static SYS_RAND_WARNING: std::sync::Once = std::sync::Once::new(); + +/// Generates random bytes. +/// +/// # Safety +/// +/// Make sure that `buf` has at least `nwords` words. +#[no_mangle] +pub unsafe extern "C" fn sys_rand(recv_buf: *mut u8, words: usize) { + SYS_RAND_WARNING.call_once(|| { + println!("WARNING: Using insecure random number generator."); + }); + let mut rng = RNG.lock().unwrap(); + for i in 0..words { + let element = recv_buf.add(i); + *element = rng.gen(); + } +} + #[allow(clippy::missing_safety_doc)] #[no_mangle] pub unsafe extern "C" fn sys_panic(msg_ptr: *const u8, len: usize) -> ! { diff --git a/zkvm/precompiles/src/bls12_381.rs b/zkvm/precompiles/src/bls12_381.rs index 3aba011d7..cfb15b411 100644 --- a/zkvm/precompiles/src/bls12_381.rs +++ b/zkvm/precompiles/src/bls12_381.rs @@ -36,7 +36,7 @@ use anyhow::Result; /// Decompresses a compressed public key using bls12381_g1_decompress precompile. pub fn decompress_pubkey(compressed_key: &[u8; 48]) -> Result<[u8; 96]> { cfg_if::cfg_if! { - if #[cfg(all(target_os = "zkvm", target_vendor = "succinct"))] { + if #[cfg(target_os = "zkvm")] { let mut decompressed_key = [0u8; 96]; decompressed_key[..48].copy_from_slice(compressed_key); unsafe { diff --git a/zkvm/precompiles/src/io.rs b/zkvm/precompiles/src/io.rs index fb684e05f..b98da2b08 100644 --- a/zkvm/precompiles/src/io.rs +++ b/zkvm/precompiles/src/io.rs @@ -7,6 +7,9 @@ use crate::{syscall_hint_len, syscall_hint_read, syscall_write}; const FD_HINT: u32 = 4; pub const FD_PUBLIC_VALUES: u32 = 3; +// Runtime hook file descriptors. Make sure these match the FDs in the HookRegistry. +// The default hooks can be found in `core/src/runtime/hooks.rs`. +pub const FD_ECRECOVER_HOOK: u32 = 5; pub struct SyscallWriter { fd: u32, @@ -79,3 +82,8 @@ pub fn hint_slice(buf: &[u8]) { let mut my_reader = SyscallWriter { fd: FD_HINT }; my_reader.write_all(buf).unwrap(); } + +/// Write the data `buf` to the file descriptor `fd` using `Write::write_all` . +pub fn write(fd: u32, buf: &[u8]) { + SyscallWriter { fd }.write_all(buf).unwrap(); +} diff --git a/zkvm/precompiles/src/lib.rs b/zkvm/precompiles/src/lib.rs index 2b9af2446..f424b4e73 100644 --- a/zkvm/precompiles/src/lib.rs +++ b/zkvm/precompiles/src/lib.rs @@ -1,3 +1,10 @@ +//! Precompiles for SP1 zkVM. +//! +//! Specifically, this crate contains user-friendly functions that call SP1 syscalls. Syscalls are +//! also declared here for convenience. In order to avoid duplicate symbol errors, the syscall +//! function impls must live in sp1-zkvm, which is only imported into the end user program crate. +//! In contrast, sp1-precompiles can be imported into any crate in the dependency tree. + pub mod bls12_381; pub mod bn254; pub mod io; @@ -7,6 +14,8 @@ pub mod utils; #[cfg(feature = "verify")] pub mod verify; +pub const BIGINT_WIDTH_WORDS: usize = 8; + extern "C" { pub fn syscall_halt(exit_code: u8) -> !; pub fn syscall_write(fd: u32, write_buf: *const u8, nbytes: usize); diff --git a/zkvm/precompiles/src/secp256k1.rs b/zkvm/precompiles/src/secp256k1.rs index 2c13da5d9..60990b144 100644 --- a/zkvm/precompiles/src/secp256k1.rs +++ b/zkvm/precompiles/src/secp256k1.rs @@ -12,8 +12,8 @@ use k256::{ }; use crate::{ - io, syscall_secp256k1_add, syscall_secp256k1_decompress, syscall_secp256k1_double, - unconstrained, + io::{self, FD_ECRECOVER_HOOK}, + syscall_secp256k1_add, syscall_secp256k1_decompress, syscall_secp256k1_double, unconstrained, utils::{AffinePoint, CurveOperations}, }; @@ -43,7 +43,7 @@ impl CurveOperations for Secp256k1Operations { /// Decompresses a compressed public key using secp256k1_decompress precompile. pub fn decompress_pubkey(compressed_key: &[u8; 33]) -> Result<[u8; 65]> { cfg_if::cfg_if! { - if #[cfg(all(target_os = "zkvm", target_vendor = "succinct"))] { + if #[cfg(target_os = "zkvm")] { let mut decompressed_key: [u8; 64] = [0; 64]; decompressed_key[..32].copy_from_slice(&compressed_key[1..]); let is_odd = match compressed_key[0] { @@ -81,7 +81,7 @@ pub fn verify_signature( s_inverse: Option<&Scalar>, ) -> bool { cfg_if::cfg_if! { - if #[cfg(all(target_os = "zkvm", target_vendor = "succinct"))] { + if #[cfg(target_os = "zkvm")] { let pubkey_x = Scalar::from_repr(bits2field::(&pubkey[1..33]).unwrap()).unwrap(); let pubkey_y = Scalar::from_repr(bits2field::(&pubkey[33..]).unwrap()).unwrap(); @@ -187,23 +187,15 @@ fn double_and_add_base( /// Either use `decompress_pubkey` and `verify_signature` to verify the results of this function, or /// use `ecrecover`. pub fn unconstrained_ecrecover(sig: &[u8; 65], msg_hash: &[u8; 32]) -> ([u8; 33], Scalar) { + // The `unconstrained!` wrapper is used since none of these computations directly affect + // the output values of the VM. The remainder of the function sets the constraints on the values + // instead. Removing the `unconstrained!` wrapper slightly increases the cycle count. unconstrained! { - let mut recovery_id = sig[64]; - let mut sig = Signature::from_slice(&sig[..64]).unwrap(); - - if let Some(sig_normalized) = sig.normalize_s() { - sig = sig_normalized; - recovery_id ^= 1 - }; - let recid = RecoveryId::from_byte(recovery_id).expect("Recovery ID is valid"); - - let recovered_key = VerifyingKey::recover_from_prehash(&msg_hash[..], &sig, recid).unwrap(); - let bytes = recovered_key.to_sec1_bytes(); - io::hint_slice(&bytes); - - let (_, s) = sig.split_scalars(); - let s_inverse = s.invert(); - io::hint_slice(&s_inverse.to_bytes()); + let mut buf = [0; 65 + 32]; + let (buf_sig, buf_msg_hash) = buf.split_at_mut(sig.len()); + buf_sig.copy_from_slice(sig); + buf_msg_hash.copy_from_slice(msg_hash); + io::write(FD_ECRECOVER_HOOK, &buf); } let recovered_bytes: [u8; 33] = io::read_vec().try_into().unwrap();