mirror of
https://github.com/eth-act/ere.git
synced 2026-02-19 11:54:42 -05:00
Add ProverResouce::Cluster and add cluster support for ZisK (#284)
This commit is contained in:
25
.github/scripts/build-image.sh
vendored
25
.github/scripts/build-image.sh
vendored
@@ -9,12 +9,13 @@ IMAGE_REGISTRY=""
|
||||
BUILD_BASE=false
|
||||
BUILD_COMPILER=false
|
||||
BUILD_SERVER=false
|
||||
BUILD_CLUSTER=false
|
||||
CUDA=false
|
||||
CUDA_ARCH=""
|
||||
RUSTFLAGS=""
|
||||
|
||||
usage() {
|
||||
echo "Usage: $0 --zkvm <zkvm> --tag <tag> [--base] [--compiler] [--server] [--registry <registry>] [--cuda] [--cuda-arch <arch>] [--rustflags <flags>]"
|
||||
echo "Usage: $0 --zkvm <zkvm> --tag <tag> [--base] [--compiler] [--server] [--cluster] [--registry <registry>] [--cuda] [--cuda-arch <arch>] [--rustflags <flags>]"
|
||||
echo ""
|
||||
echo "Required:"
|
||||
echo " --zkvm <zkvm> zkVM to build for (e.g., zisk, sp1, risc0)"
|
||||
@@ -24,6 +25,7 @@ usage() {
|
||||
echo " --base Build the base images"
|
||||
echo " --compiler Build the compiler image"
|
||||
echo " --server Build the server image"
|
||||
echo " --cluster Build the cluster image"
|
||||
echo ""
|
||||
echo "Optional:"
|
||||
echo " --registry <reg> Registry prefix (e.g., ghcr.io/eth-act/ere)"
|
||||
@@ -60,6 +62,10 @@ while [[ $# -gt 0 ]]; do
|
||||
BUILD_SERVER=true
|
||||
shift
|
||||
;;
|
||||
--cluster)
|
||||
BUILD_CLUSTER=true
|
||||
shift
|
||||
;;
|
||||
--cuda)
|
||||
CUDA=true
|
||||
shift
|
||||
@@ -93,8 +99,8 @@ if [ -z "$IMAGE_TAG" ]; then
|
||||
usage
|
||||
fi
|
||||
|
||||
if [ "$BUILD_BASE" = false ] && [ "$BUILD_COMPILER" = false ] && [ "$BUILD_SERVER" = false ]; then
|
||||
echo "Error: At least one of --base, --compiler, --server is required"
|
||||
if [ "$BUILD_BASE" = false ] && [ "$BUILD_COMPILER" = false ] && [ "$BUILD_SERVER" = false ] && [ "$BUILD_CLUSTER" = false ]; then
|
||||
echo "Error: At least one of --base, --compiler, --server, --cluster is required"
|
||||
usage
|
||||
fi
|
||||
|
||||
@@ -118,6 +124,7 @@ BASE_IMAGE="${IMAGE_PREFIX}ere-base:${IMAGE_TAG}"
|
||||
BASE_ZKVM_IMAGE="${IMAGE_PREFIX}ere-base-${ZKVM}:${IMAGE_TAG}"
|
||||
COMPILER_ZKVM_IMAGE="${IMAGE_PREFIX}ere-compiler-${ZKVM}:${IMAGE_TAG}"
|
||||
SERVER_ZKVM_IMAGE="${IMAGE_PREFIX}ere-server-${ZKVM}:${IMAGE_TAG}"
|
||||
CLUSTER_ZKVM_IMAGE="${IMAGE_PREFIX}ere-cluster-${ZKVM}:${IMAGE_TAG}"
|
||||
|
||||
# Prepare build arguments
|
||||
|
||||
@@ -125,16 +132,19 @@ BASE_BUILD_ARGS=()
|
||||
BASE_ZKVM_BUILD_ARGS=(--build-arg "BASE_IMAGE=$BASE_IMAGE")
|
||||
COMPILER_ZKVM_BUILD_ARGS=(--build-arg "BASE_ZKVM_IMAGE=$BASE_ZKVM_IMAGE")
|
||||
SERVER_ZKVM_BUILD_ARGS=(--build-arg "BASE_ZKVM_IMAGE=$BASE_ZKVM_IMAGE")
|
||||
CLUSTER_ZKVM_BUILD_ARGS=()
|
||||
|
||||
if [ "$CUDA" = true ]; then
|
||||
BASE_BUILD_ARGS+=(--build-arg "CUDA=1")
|
||||
BASE_ZKVM_BUILD_ARGS+=(--build-arg "CUDA=1")
|
||||
SERVER_ZKVM_BUILD_ARGS+=(--build-arg "CUDA=1")
|
||||
CLUSTER_ZKVM_BUILD_ARGS+=(--build-arg "CUDA=1")
|
||||
fi
|
||||
|
||||
if [ -n "$CUDA_ARCH" ]; then
|
||||
BASE_ZKVM_BUILD_ARGS+=(--build-arg "CUDA_ARCH=$CUDA_ARCH")
|
||||
SERVER_ZKVM_BUILD_ARGS+=(--build-arg "CUDA_ARCH=$CUDA_ARCH")
|
||||
CLUSTER_ZKVM_BUILD_ARGS+=(--build-arg "CUDA_ARCH=$CUDA_ARCH")
|
||||
fi
|
||||
|
||||
if [ -n "$RUSTFLAGS" ]; then
|
||||
@@ -178,4 +188,13 @@ if [ "$BUILD_SERVER" = true ]; then
|
||||
.
|
||||
fi
|
||||
|
||||
if [ "$BUILD_CLUSTER" = true ]; then
|
||||
echo "Building zkvm cluster image: $CLUSTER_ZKVM_IMAGE"
|
||||
docker build \
|
||||
--file "docker/${ZKVM}/Dockerfile.cluster" \
|
||||
--tag "$CLUSTER_ZKVM_IMAGE" \
|
||||
"${CLUSTER_ZKVM_BUILD_ARGS[@]}" \
|
||||
.
|
||||
fi
|
||||
|
||||
echo "Build complete!"
|
||||
|
||||
597
Cargo.lock
generated
597
Cargo.lock
generated
@@ -2145,6 +2145,16 @@ dependencies = [
|
||||
"tinyvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "build-probe-mpi"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d78ace2bb02fc18ad937f1599a853fcf3da2327bc1eb3c8e62b1f2fe4573bfd6"
|
||||
dependencies = [
|
||||
"pkg-config",
|
||||
"shell-words",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.17.0"
|
||||
@@ -2333,10 +2343,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.22"
|
||||
version = "1.2.55"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32db95edf998450acc7881c932f94cd9b05c87b4b2599e8bab064753da4acfd1"
|
||||
checksum = "47b26a0954ae34af09b50f0de26458fa95369a0d478d8236d3f93082b219bd29"
|
||||
dependencies = [
|
||||
"find-msvc-tools",
|
||||
"jobserver",
|
||||
"libc",
|
||||
"shlex",
|
||||
@@ -2573,6 +2584,15 @@ version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
|
||||
|
||||
[[package]]
|
||||
name = "colored"
|
||||
version = "3.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "faf9468729b8cbcea668e36183cb69d317348c2e08e994829fb56ebfdfbaac34"
|
||||
dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "common"
|
||||
version = "0.2.0"
|
||||
@@ -2688,6 +2708,15 @@ version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6"
|
||||
|
||||
[[package]]
|
||||
name = "conv"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78ff10625fd0ac447827aa30ea8b861fead473bb60aeb73af6c1c58caf0d1299"
|
||||
dependencies = [
|
||||
"custom_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "convert_case"
|
||||
version = "0.7.1"
|
||||
@@ -3059,6 +3088,23 @@ dependencies = [
|
||||
"syn 2.0.101",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "curves"
|
||||
version = "0.15.0"
|
||||
source = "git+https://github.com/0xPolygonHermez/pil2-proofman?tag=v0.15.0#78497c5a05ea316df2188f98c1df66bffb80192f"
|
||||
dependencies = [
|
||||
"fields",
|
||||
"num-bigint 0.4.6",
|
||||
"num-traits",
|
||||
"rand 0.9.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "custom_derive"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef8ae57c4978a2acd8b869ce6b9ca1dfe817bff704c220209fdef2c0b75a01b9"
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.20.11"
|
||||
@@ -3784,6 +3830,15 @@ dependencies = [
|
||||
"syn 2.0.101",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "env"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc95de49ad098572c02d3fbf368c9a020bfff5ae78483685b77f51d8a7e9486d"
|
||||
dependencies = [
|
||||
"num_threads",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "env_filter"
|
||||
version = "0.1.3"
|
||||
@@ -4206,12 +4261,20 @@ dependencies = [
|
||||
"ere-compile-utils",
|
||||
"ere-test-utils",
|
||||
"ere-zkvm-interface",
|
||||
"futures-util",
|
||||
"http 1.3.1",
|
||||
"parking_lot",
|
||||
"proofman-verifier",
|
||||
"serde",
|
||||
"strum 0.27.2",
|
||||
"tempfile",
|
||||
"thiserror 2.0.12",
|
||||
"tokio",
|
||||
"tonic 0.14.3",
|
||||
"tracing",
|
||||
"uuid 1.17.0",
|
||||
"wait-timeout",
|
||||
"zisk-distributed-grpc-api",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4224,7 +4287,6 @@ dependencies = [
|
||||
"clap",
|
||||
"indexmap 2.10.0",
|
||||
"serde",
|
||||
"serde-untagged",
|
||||
"serde_json",
|
||||
"serde_yaml",
|
||||
"strum 0.27.2",
|
||||
@@ -4557,7 +4619,7 @@ dependencies = [
|
||||
"tokio",
|
||||
"tracing",
|
||||
"walkdir",
|
||||
"yansi",
|
||||
"yansi 0.5.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4697,6 +4759,16 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fields"
|
||||
version = "0.15.0"
|
||||
source = "git+https://github.com/0xPolygonHermez/pil2-proofman?tag=v0.15.0#78497c5a05ea316df2188f98c1df66bffb80192f"
|
||||
dependencies = [
|
||||
"num-bigint 0.4.6",
|
||||
"paste",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "final_reduced_risc_v_machine"
|
||||
version = "0.1.0"
|
||||
@@ -4709,6 +4781,12 @@ dependencies = [
|
||||
"verifier_generator",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "find-msvc-tools"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
|
||||
|
||||
[[package]]
|
||||
name = "findshlibs"
|
||||
version = "0.10.2"
|
||||
@@ -6522,6 +6600,25 @@ version = "0.2.175"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543"
|
||||
|
||||
[[package]]
|
||||
name = "libffi"
|
||||
version = "3.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce826c243048e3d5cec441799724de52e2d42f820468431fc3fceee2341871e2"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"libffi-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libffi-sys"
|
||||
version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f36115160c57e8529781b4183c2bb51fdc1f6d6d1ed345591d84be7703befb3c"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libgit2-sys"
|
||||
version = "0.17.0+1.8.1"
|
||||
@@ -7260,6 +7357,32 @@ dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mpi"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "677762a4bde2c81158fc566a69b97d11b0c3358694e64f4f922ac5189be311cc"
|
||||
dependencies = [
|
||||
"build-probe-mpi",
|
||||
"conv",
|
||||
"libffi",
|
||||
"mpi-sys",
|
||||
"once_cell",
|
||||
"smallvec",
|
||||
"thiserror 1.0.69",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mpi-sys"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f655543f54b263cbc3d2456bf714bd807d66a33eff8f70136687f0776d34f76"
|
||||
dependencies = [
|
||||
"bindgen 0.69.5",
|
||||
"build-probe-mpi",
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "multimap"
|
||||
version = "0.8.3"
|
||||
@@ -7857,6 +7980,25 @@ dependencies = [
|
||||
"malloc_buf",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-foundation"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536"
|
||||
dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-io-kit"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33fafba39597d6dc1fb709123dfa8289d39406734be322956a69f0931c73bb15"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"objc2-core-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.35.0"
|
||||
@@ -10244,6 +10386,15 @@ dependencies = [
|
||||
"group 0.13.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "papergrid"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "608b6444acf7f5ea39e8bd06dd6037e34a4b5ddfb29ae840edad49ea798e9e79"
|
||||
dependencies = [
|
||||
"unicode-width 0.1.14",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parity-scale-codec"
|
||||
version = "3.7.4"
|
||||
@@ -10433,6 +10584,17 @@ dependencies = [
|
||||
"indexmap 2.10.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "petgraph"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455"
|
||||
dependencies = [
|
||||
"fixedbitset 0.5.7",
|
||||
"hashbrown 0.15.3",
|
||||
"indexmap 2.10.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pharos"
|
||||
version = "0.5.3"
|
||||
@@ -10605,7 +10767,7 @@ dependencies = [
|
||||
"static_assertions",
|
||||
"strum 0.26.3",
|
||||
"strum_macros 0.26.4",
|
||||
"sysinfo",
|
||||
"sysinfo 0.30.13",
|
||||
"thiserror 1.0.69",
|
||||
"tiny-keccak",
|
||||
"tracing",
|
||||
@@ -10616,6 +10778,23 @@ dependencies = [
|
||||
"zkhash 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pil-std-lib"
|
||||
version = "0.15.0"
|
||||
source = "git+https://github.com/0xPolygonHermez/pil2-proofman?tag=v0.15.0#78497c5a05ea316df2188f98c1df66bffb80192f"
|
||||
dependencies = [
|
||||
"colored",
|
||||
"fields",
|
||||
"num-bigint 0.4.6",
|
||||
"num-traits",
|
||||
"proofman-common",
|
||||
"proofman-hints",
|
||||
"proofman-util",
|
||||
"rayon",
|
||||
"tracing",
|
||||
"witness",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project"
|
||||
version = "1.1.10"
|
||||
@@ -10874,6 +11053,126 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proofman"
|
||||
version = "0.15.0"
|
||||
source = "git+https://github.com/0xPolygonHermez/pil2-proofman?tag=v0.15.0#78497c5a05ea316df2188f98c1df66bffb80192f"
|
||||
dependencies = [
|
||||
"blake3",
|
||||
"borsh",
|
||||
"bytemuck",
|
||||
"chrono",
|
||||
"colored",
|
||||
"crossbeam-channel",
|
||||
"csv",
|
||||
"curves",
|
||||
"fields",
|
||||
"libloading 0.8.7",
|
||||
"mpi",
|
||||
"num-bigint 0.4.6",
|
||||
"num-traits",
|
||||
"pil-std-lib",
|
||||
"proofman-common",
|
||||
"proofman-hints",
|
||||
"proofman-macros",
|
||||
"proofman-starks-lib-c",
|
||||
"proofman-util",
|
||||
"proofman-verifier",
|
||||
"rand 0.9.2",
|
||||
"rayon",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
"tracing",
|
||||
"witness",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proofman-common"
|
||||
version = "0.15.0"
|
||||
source = "git+https://github.com/0xPolygonHermez/pil2-proofman?tag=v0.15.0#78497c5a05ea316df2188f98c1df66bffb80192f"
|
||||
dependencies = [
|
||||
"borsh",
|
||||
"colored",
|
||||
"crossbeam-channel",
|
||||
"crossbeam-queue",
|
||||
"csv",
|
||||
"env",
|
||||
"fields",
|
||||
"indexmap 2.10.0",
|
||||
"lazy_static",
|
||||
"libloading 0.8.7",
|
||||
"mpi",
|
||||
"num_cpus",
|
||||
"proofman-macros",
|
||||
"proofman-starks-lib-c",
|
||||
"proofman-util",
|
||||
"rayon",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sysinfo 0.35.2",
|
||||
"tabled",
|
||||
"thiserror 2.0.12",
|
||||
"tracing",
|
||||
"tracing-subscriber 0.3.20",
|
||||
"yansi 1.0.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proofman-hints"
|
||||
version = "0.15.0"
|
||||
source = "git+https://github.com/0xPolygonHermez/pil2-proofman?tag=v0.15.0#78497c5a05ea316df2188f98c1df66bffb80192f"
|
||||
dependencies = [
|
||||
"fields",
|
||||
"proofman-common",
|
||||
"proofman-starks-lib-c",
|
||||
"proofman-util",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proofman-macros"
|
||||
version = "0.15.0"
|
||||
source = "git+https://github.com/0xPolygonHermez/pil2-proofman?tag=v0.15.0#78497c5a05ea316df2188f98c1df66bffb80192f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rayon",
|
||||
"syn 2.0.101",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proofman-starks-lib-c"
|
||||
version = "0.15.0"
|
||||
source = "git+https://github.com/0xPolygonHermez/pil2-proofman?tag=v0.15.0#78497c5a05ea316df2188f98c1df66bffb80192f"
|
||||
dependencies = [
|
||||
"crossbeam-channel",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proofman-util"
|
||||
version = "0.15.0"
|
||||
source = "git+https://github.com/0xPolygonHermez/pil2-proofman?tag=v0.15.0#78497c5a05ea316df2188f98c1df66bffb80192f"
|
||||
dependencies = [
|
||||
"colored",
|
||||
"fields",
|
||||
"sysinfo 0.35.2",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proofman-verifier"
|
||||
version = "0.15.0"
|
||||
source = "git+https://github.com/0xPolygonHermez/pil2-proofman?tag=v0.15.0#78497c5a05ea316df2188f98c1df66bffb80192f"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"fields",
|
||||
"rayon",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proptest"
|
||||
version = "1.9.0"
|
||||
@@ -10923,6 +11222,16 @@ dependencies = [
|
||||
"prost-derive 0.13.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prost"
|
||||
version = "0.14.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2ea70524a2f82d518bce41317d0fae74151505651af45faf1ffbd6fd33f0568"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"prost-derive 0.14.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prost-build"
|
||||
version = "0.11.9"
|
||||
@@ -10986,6 +11295,27 @@ dependencies = [
|
||||
"tempfile",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prost-build"
|
||||
version = "0.14.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "343d3bd7056eda839b03204e68deff7d1b13aba7af2b2fd16890697274262ee7"
|
||||
dependencies = [
|
||||
"heck 0.5.0",
|
||||
"itertools 0.14.0",
|
||||
"log",
|
||||
"multimap 0.10.1",
|
||||
"petgraph 0.8.3",
|
||||
"prettyplease 0.2.32",
|
||||
"prost 0.14.3",
|
||||
"prost-types 0.14.3",
|
||||
"pulldown-cmark",
|
||||
"pulldown-cmark-to-cmark",
|
||||
"regex",
|
||||
"syn 2.0.101",
|
||||
"tempfile",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prost-derive"
|
||||
version = "0.11.9"
|
||||
@@ -11025,6 +11355,19 @@ dependencies = [
|
||||
"syn 2.0.101",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prost-derive"
|
||||
version = "0.14.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "27c6023962132f4b30eb4c172c91ce92d933da334c59c23cddee82358ddafb0b"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"itertools 0.14.0",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.101",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prost-types"
|
||||
version = "0.11.9"
|
||||
@@ -11052,6 +11395,15 @@ dependencies = [
|
||||
"prost 0.13.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prost-types"
|
||||
version = "0.14.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8991c4cbdb8bc5b11f0b074ffe286c30e523de90fee5ba8132f1399f23cb3dd7"
|
||||
dependencies = [
|
||||
"prost 0.14.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prover"
|
||||
version = "0.1.0"
|
||||
@@ -11114,6 +11466,26 @@ dependencies = [
|
||||
"parking_lot",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pulldown-cmark"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e8bbe1a966bd2f362681a44f6edce3c2310ac21e4d5067a6e7ec396297a6ea0"
|
||||
dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
"memchr",
|
||||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pulldown-cmark-to-cmark"
|
||||
version = "22.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50793def1b900256624a709439404384204a5dc3a6ec580281bfaac35e882e90"
|
||||
dependencies = [
|
||||
"pulldown-cmark",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quanta"
|
||||
version = "0.12.5"
|
||||
@@ -12772,18 +13144,6 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde-untagged"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9faf48a4a2d2693be24c6289dbe26552776eb7737074e6722891fadbe6c5058"
|
||||
dependencies = [
|
||||
"erased-serde",
|
||||
"serde",
|
||||
"serde_core",
|
||||
"typeid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_arrays"
|
||||
version = "0.1.0"
|
||||
@@ -12838,6 +13198,7 @@ version = "1.0.142"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "030fedb782600dcbd6f02d479bf0d817ac3bb40d644745b769d6a96bc3afc5a7"
|
||||
dependencies = [
|
||||
"indexmap 2.10.0",
|
||||
"itoa",
|
||||
"memchr",
|
||||
"ryu",
|
||||
@@ -13034,6 +13395,12 @@ dependencies = [
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shell-words"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc6fe69c597f9c37bfeeeeeb33da3530379845f10be461a66d16d03eca2ded77"
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.3.0"
|
||||
@@ -13596,7 +13963,7 @@ dependencies = [
|
||||
"sp1-stark",
|
||||
"strum 0.26.3",
|
||||
"strum_macros 0.26.4",
|
||||
"sysinfo",
|
||||
"sysinfo 0.30.13",
|
||||
"tempfile",
|
||||
"thiserror 1.0.69",
|
||||
"tokio",
|
||||
@@ -13635,7 +14002,7 @@ dependencies = [
|
||||
"sp1-derive",
|
||||
"sp1-primitives",
|
||||
"strum 0.26.3",
|
||||
"sysinfo",
|
||||
"sysinfo 0.30.13",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
@@ -14104,6 +14471,20 @@ dependencies = [
|
||||
"windows 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sysinfo"
|
||||
version = "0.35.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c3ffa3e4ff2b324a57f7aeb3c349656c7b127c3c189520251a648102a92496e"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"memchr",
|
||||
"ntapi",
|
||||
"objc2-core-foundation",
|
||||
"objc2-io-kit",
|
||||
"windows 0.61.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "system-configuration"
|
||||
version = "0.5.1"
|
||||
@@ -14146,6 +14527,27 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tabled"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2407502760ccfd538f2fb1f843dd87b6daf1a17848d57bc5a25617e408ef4c7a"
|
||||
dependencies = [
|
||||
"papergrid",
|
||||
"tabled_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tabled_derive"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "278ea3921cee8c5a69e0542998a089f7a14fa43c9c4e4f9951295da89bd0c943"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tap"
|
||||
version = "1.0.1"
|
||||
@@ -14486,9 +14888,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tokio-util"
|
||||
version = "0.7.15"
|
||||
version = "0.7.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df"
|
||||
checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-core",
|
||||
@@ -14656,6 +15058,35 @@ dependencies = [
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tonic"
|
||||
version = "0.14.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a286e33f82f8a1ee2df63f4fa35c0becf4a85a0cb03091a15fd7bf0b402dc94a"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"axum 0.8.5",
|
||||
"base64 0.22.1",
|
||||
"bytes",
|
||||
"h2 0.4.10",
|
||||
"http 1.3.1",
|
||||
"http-body 1.0.1",
|
||||
"http-body-util",
|
||||
"hyper 1.6.0",
|
||||
"hyper-timeout 0.5.2",
|
||||
"hyper-util",
|
||||
"percent-encoding",
|
||||
"pin-project",
|
||||
"socket2 0.6.0",
|
||||
"sync_wrapper 1.0.2",
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
"tower 0.5.2",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tonic-build"
|
||||
version = "0.8.4"
|
||||
@@ -14669,6 +15100,45 @@ dependencies = [
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tonic-build"
|
||||
version = "0.14.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "27aac809edf60b741e2d7db6367214d078856b8a5bff0087e94ff330fb97b6fc"
|
||||
dependencies = [
|
||||
"prettyplease 0.2.32",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.101",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tonic-prost"
|
||||
version = "0.14.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d6c55a2d6a14174563de34409c9f92ff981d006f56da9c6ecd40d9d4a31500b0"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"prost 0.14.3",
|
||||
"tonic 0.14.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tonic-prost-build"
|
||||
version = "0.14.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4556786613791cfef4ed134aa670b61a85cfcacf71543ef33e8d801abae988f"
|
||||
dependencies = [
|
||||
"prettyplease 0.2.32",
|
||||
"proc-macro2",
|
||||
"prost-build 0.14.3",
|
||||
"prost-types 0.14.3",
|
||||
"quote",
|
||||
"syn 2.0.101",
|
||||
"tempfile",
|
||||
"tonic-build 0.14.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tower"
|
||||
version = "0.4.13"
|
||||
@@ -14697,9 +15167,12 @@ checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"indexmap 2.10.0",
|
||||
"pin-project-lite",
|
||||
"slab",
|
||||
"sync_wrapper 1.0.2",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
@@ -14870,6 +15343,16 @@ dependencies = [
|
||||
"tracing-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-serde"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "704b1aeb7be0d0a84fc9828cae51dab5970fee5088f83d1dd7ee6f6246fc6ff1"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"tracing-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-subscriber"
|
||||
version = "0.2.25"
|
||||
@@ -14889,12 +15372,15 @@ dependencies = [
|
||||
"nu-ansi-term",
|
||||
"once_cell",
|
||||
"regex-automata",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sharded-slab",
|
||||
"smallvec",
|
||||
"thread_local",
|
||||
"tracing",
|
||||
"tracing-core",
|
||||
"tracing-log",
|
||||
"tracing-serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -15159,6 +15645,12 @@ version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94"
|
||||
|
||||
[[package]]
|
||||
name = "unicase"
|
||||
version = "2.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.18"
|
||||
@@ -15293,6 +15785,7 @@ dependencies = [
|
||||
"getrandom 0.3.3",
|
||||
"js-sys",
|
||||
"rand 0.9.2",
|
||||
"serde",
|
||||
"uuid-macro-internal",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
@@ -16144,6 +16637,20 @@ dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "witness"
|
||||
version = "0.15.0"
|
||||
source = "git+https://github.com/0xPolygonHermez/pil2-proofman?tag=v0.15.0#78497c5a05ea316df2188f98c1df66bffb80192f"
|
||||
dependencies = [
|
||||
"colored",
|
||||
"fields",
|
||||
"libloading 0.8.7",
|
||||
"proofman-common",
|
||||
"proofman-util",
|
||||
"serde_json",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "worker"
|
||||
version = "0.1.0"
|
||||
@@ -16220,6 +16727,12 @@ version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
|
||||
|
||||
[[package]]
|
||||
name = "yansi"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049"
|
||||
|
||||
[[package]]
|
||||
name = "yoke"
|
||||
version = "0.8.0"
|
||||
@@ -16375,6 +16888,44 @@ dependencies = [
|
||||
"zopfli",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zisk-distributed-common"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/han0110/zisk?branch=patch%2Fv0.15.0-cluster#6ffe5f4123a258765cf814c5ff3d3bb8988fb964"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"borsh",
|
||||
"chrono",
|
||||
"proofman",
|
||||
"proofman-common",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror 2.0.12",
|
||||
"tracing",
|
||||
"tracing-appender",
|
||||
"tracing-subscriber 0.3.20",
|
||||
"uuid 1.17.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zisk-distributed-grpc-api"
|
||||
version = "0.15.0"
|
||||
source = "git+https://github.com/han0110/zisk?branch=patch%2Fv0.15.0-cluster#6ffe5f4123a258765cf814c5ff3d3bb8988fb964"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"chrono",
|
||||
"prost 0.14.3",
|
||||
"prost-types 0.14.3",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tonic 0.14.3",
|
||||
"tonic-prost",
|
||||
"tonic-prost-build",
|
||||
"tracing",
|
||||
"uuid 1.17.0",
|
||||
"zisk-distributed-common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ziskos"
|
||||
version = "0.15.0"
|
||||
@@ -16838,7 +17389,7 @@ dependencies = [
|
||||
"thiserror 1.0.69",
|
||||
"tokio",
|
||||
"tonic 0.8.3",
|
||||
"tonic-build",
|
||||
"tonic-build 0.8.4",
|
||||
"tracing",
|
||||
"twirp-rs",
|
||||
"uuid 1.17.0",
|
||||
@@ -16885,7 +17436,7 @@ dependencies = [
|
||||
"serde",
|
||||
"strum 0.26.3",
|
||||
"strum_macros 0.26.4",
|
||||
"sysinfo",
|
||||
"sysinfo 0.30.13",
|
||||
"tracing",
|
||||
"tracing-forest",
|
||||
"tracing-subscriber 0.3.20",
|
||||
|
||||
10
Cargo.toml
10
Cargo.toml
@@ -49,7 +49,7 @@ anyhow = "1.0.98"
|
||||
auto_impl = "1.3.0"
|
||||
bincode = { version = "2.0.1", default-features = false }
|
||||
blake3 = "1.8.2"
|
||||
bytemuck = "1.24.0"
|
||||
bytemuck = "1.25.0"
|
||||
cargo_metadata = "0.19.0"
|
||||
ciborium = { version = "0.2.2", default-features = false }
|
||||
ciborium-io = { version = "0.2.2", default-features = false }
|
||||
@@ -58,7 +58,10 @@ dashmap = "6.1.0"
|
||||
digest = { version = "0.10.7", default-features = false }
|
||||
eyre = "0.6.12"
|
||||
fnv = { version = "1.0.7", default-features = false }
|
||||
futures-util = "0.3"
|
||||
http = "1"
|
||||
indexmap = "2.10.0"
|
||||
parking_lot = "0.12.5"
|
||||
paste = "1.0.15"
|
||||
postcard = { version = "1.0.8", default-features = false }
|
||||
prost = "0.13"
|
||||
@@ -68,7 +71,6 @@ rkyv = { version = "0.8.12", default-features = false }
|
||||
serde = { version = "1.0.219", default-features = false }
|
||||
serde_bytes = { version = "0.11.19", default-features = false }
|
||||
serde_json = "1.0.142"
|
||||
serde-untagged = "0.1"
|
||||
serde_yaml = "0.9.34"
|
||||
sha2 = { version = "0.10.9", default-features = false }
|
||||
strum = "0.27.2"
|
||||
@@ -76,11 +78,13 @@ tempfile = "3.20.0"
|
||||
thiserror = "2.0.12"
|
||||
tokio = "1.0"
|
||||
toml = "0.8.23"
|
||||
tonic = "0.14"
|
||||
tower-http = "0.6.6"
|
||||
tracing = "0.1.41"
|
||||
tracing-subscriber = "0.3.19"
|
||||
twirp = "0.9.1"
|
||||
twirp-build = "0.9.0"
|
||||
uuid = "1"
|
||||
wait-timeout = "0.2.1"
|
||||
|
||||
# Airbender dependencies
|
||||
@@ -140,6 +144,8 @@ zkm-zkvm = { git = "https://github.com/ProjectZKM/Ziren.git", tag = "v1.2.3", de
|
||||
|
||||
# ZisK dependencies
|
||||
ziskos = { git = "https://github.com/0xPolygonHermez/zisk.git", tag = "v0.15.0" }
|
||||
zisk-distributed-grpc-api = { git = "https://github.com/han0110/zisk", branch = "patch/v0.15.0-cluster" }
|
||||
zisk-proofman-verifier = { git = "https://github.com/0xPolygonHermez/pil2-proofman", package = "proofman-verifier", tag = "v0.15.0" }
|
||||
|
||||
# Local dependencies
|
||||
ere-zkvm-interface = { path = "crates/zkvm-interface" }
|
||||
|
||||
10
README.md
10
README.md
@@ -184,7 +184,7 @@ OutputHashedPlatform::<OpenVMPlatform, Sha256>::write_whole_output(&large_output
|
||||
| Risc0 | [`3.0.4`](https://github.com/risc0/risc0/tree/v3.0.4) | Yes |
|
||||
| SP1 | [`5.2.4`](https://github.com/succinctlabs/sp1/tree/v5.2.4) | Yes |
|
||||
| Ziren | [`1.2.3`](https://github.com/ProjectZKM/Ziren/tree/v1.2.3) | No |
|
||||
| Zisk | [`0.13.0`](https://github.com/0xPolygonHermez/zisk/tree/v0.13.0) | Yes |
|
||||
| Zisk | [`0.15.0`](https://github.com/0xPolygonHermez/zisk/tree/v0.15.0) | Yes |
|
||||
|
||||
## Examples
|
||||
|
||||
@@ -273,7 +273,7 @@ ere-sp1 = { git = "https://github.com/eth-act/ere.git" }
|
||||
use ere_sp1::{compiler::RustRv32imaCustomized, zkvm::EreSP1};
|
||||
use ere_zkvm_interface::{
|
||||
compiler::Compiler,
|
||||
zkvm::{Input, ProofKind, ProverResourceType, zkVM},
|
||||
zkvm::{Input, ProofKind, ProverResource, zkVM},
|
||||
};
|
||||
use std::path::Path;
|
||||
|
||||
@@ -285,7 +285,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let program = compiler.compile(guest_directory)?;
|
||||
|
||||
// Create zkVM instance (setup/preprocessing happens here)
|
||||
let zkvm = EreSP1::new(program, ProverResourceType::Cpu)?;
|
||||
let zkvm = EreSP1::new(program, ProverResource::Cpu)?;
|
||||
|
||||
// Prepare input
|
||||
// Use `with_prefixed_stdin` when guest uses `Platform::read_whole_input()`
|
||||
@@ -341,7 +341,7 @@ ere-dockerized = { git = "https://github.com/eth-act/ere.git" }
|
||||
use ere_dockerized::{CompilerKind, DockerizedCompiler, DockerizedzkVM, zkVMKind};
|
||||
use ere_zkvm_interface::{
|
||||
compiler::Compiler,
|
||||
zkvm::{Input, ProofKind, ProverResourceType, zkVM},
|
||||
zkvm::{Input, ProofKind, ProverResource, zkVM},
|
||||
};
|
||||
use std::path::Path;
|
||||
|
||||
@@ -355,7 +355,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
|
||||
// Create zkVM instance (builds Docker images if needed)
|
||||
// It spawns a container that runs a gRPC server handling zkVM operations
|
||||
let zkvm = DockerizedzkVM::new(zkVMKind::SP1, program, ProverResourceType::Cpu)?;
|
||||
let zkvm = DockerizedzkVM::new(zkVMKind::SP1, program, ProverResource::Cpu)?;
|
||||
|
||||
// Prepare input
|
||||
// Use `with_prefixed_stdin` when guest uses `Platform::read_whole_input()`
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use anyhow::{Context, Error};
|
||||
use clap::Parser;
|
||||
use ere_server::server::{router, zkVMServer};
|
||||
use ere_zkvm_interface::zkvm::{ProverResourceType, zkVM};
|
||||
use ere_zkvm_interface::zkvm::{ProverResource, zkVM};
|
||||
use std::{
|
||||
io::{self, Read},
|
||||
net::{Ipv4Addr, SocketAddr},
|
||||
@@ -48,7 +48,7 @@ struct Args {
|
||||
program_path: Option<String>,
|
||||
/// Prover resource type.
|
||||
#[command(subcommand)]
|
||||
resource: ProverResourceType,
|
||||
resource: ProverResource,
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
@@ -120,7 +120,7 @@ async fn shutdown_signal() {
|
||||
}
|
||||
}
|
||||
|
||||
fn construct_zkvm(program: Vec<u8>, resource: ProverResourceType) -> Result<impl zkVM, Error> {
|
||||
fn construct_zkvm(program: Vec<u8>, resource: ProverResource) -> Result<impl zkVM, Error> {
|
||||
let (program, _) = bincode::serde::decode_from_slice(&program, bincode::config::legacy())
|
||||
.with_context(|| "Failed to deserialize program")?;
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
//! 4. `ere-server-{zkvm}:{version}` - Server image with the `ere-server` binary
|
||||
//! built with the selected zkVM feature
|
||||
//!
|
||||
//! When [`ProverResourceType::Gpu`] is selected, the image with GPU support
|
||||
//! When [`ProverResource::Gpu`] is selected, the image with GPU support
|
||||
//! will be built and tagged with specific suffix.
|
||||
//!
|
||||
//! To force rebuild all images, set the environment variable
|
||||
@@ -29,7 +29,7 @@
|
||||
//! use ere_dockerized::{CompilerKind, DockerizedCompiler, DockerizedzkVM, zkVMKind};
|
||||
//! use ere_zkvm_interface::{
|
||||
//! compiler::Compiler,
|
||||
//! zkvm::{Input, ProofKind, ProverResourceType, zkVM},
|
||||
//! zkvm::{Input, ProofKind, ProverResource, zkVM},
|
||||
//! };
|
||||
//! use std::path::Path;
|
||||
//!
|
||||
@@ -45,7 +45,7 @@
|
||||
//! let program = compiler.compile(&guest_path)?;
|
||||
//!
|
||||
//! // Create zkVM instance
|
||||
//! let resource = ProverResourceType::Cpu;
|
||||
//! let resource = ProverResource::Cpu;
|
||||
//! let zkvm = DockerizedzkVM::new(zkvm_kind, program, resource)?;
|
||||
//!
|
||||
//! // Serialize input
|
||||
|
||||
@@ -22,7 +22,7 @@ use ere_server::{
|
||||
use ere_zkvm_interface::{
|
||||
CommonError,
|
||||
zkvm::{
|
||||
Input, ProgramExecutionReport, ProgramProvingReport, Proof, ProofKind, ProverResourceType,
|
||||
Input, ProgramExecutionReport, ProgramProvingReport, Proof, ProofKind, ProverResource,
|
||||
PublicValues, zkVM,
|
||||
},
|
||||
};
|
||||
@@ -47,7 +47,7 @@ pub use error::Error;
|
||||
/// 3. `ere-server-{zkvm}:{version}` - Server image with the `ere-server` binary
|
||||
/// built with the selected zkVM feature
|
||||
///
|
||||
/// When [`ProverResourceType::Gpu`] is selected, the image with GPU support
|
||||
/// When [`ProverResource::Gpu`] is selected, the image with GPU support
|
||||
/// will be built and tagged with specific suffix.
|
||||
///
|
||||
/// Images are cached and only rebuilt if they don't exist or if the
|
||||
@@ -158,12 +158,12 @@ impl ServerContainer {
|
||||
fn new(
|
||||
zkvm_kind: zkVMKind,
|
||||
program: &SerializedProgram,
|
||||
resource: &ProverResourceType,
|
||||
resource: &ProverResource,
|
||||
) -> Result<Self, Error> {
|
||||
let port = Self::PORT_OFFSET + zkvm_kind as u16;
|
||||
|
||||
let name = format!("ere-server-{zkvm_kind}");
|
||||
let gpu = matches!(resource, ProverResourceType::Gpu);
|
||||
let gpu = resource.is_gpu();
|
||||
let mut cmd = DockerRunCmd::new(server_zkvm_image(zkvm_kind, gpu))
|
||||
.rm()
|
||||
.inherit_env("RUST_LOG")
|
||||
@@ -181,23 +181,25 @@ impl ServerContainer {
|
||||
// zkVM specific options
|
||||
cmd = match zkvm_kind {
|
||||
zkVMKind::Risc0 => cmd
|
||||
.inherit_env("RISC0_SEGMENT_PO2")
|
||||
.inherit_env("RISC0_KECCAK_PO2"),
|
||||
.inherit_env("ERE_RISC0_SEGMENT_PO2")
|
||||
.inherit_env("ERE_RISC0_KECCAK_PO2"),
|
||||
// ZisK uses shared memory to exchange data between processes, it
|
||||
// requires at least 16G shared memory, here we set 32G for safety.
|
||||
zkVMKind::Zisk => cmd
|
||||
.option("shm-size", "32G")
|
||||
.option("ulimit", "memlock=-1:-1")
|
||||
.inherit_env("ZISK_PORT")
|
||||
.inherit_env("ZISK_CHUNK_SIZE_BITS")
|
||||
.inherit_env("ZISK_UNLOCK_MAPPED_MEMORY")
|
||||
.inherit_env("ZISK_MINIMAL_MEMORY")
|
||||
.inherit_env("ZISK_PREALLOCATE")
|
||||
.inherit_env("ZISK_SHARED_TABLES")
|
||||
.inherit_env("ZISK_MAX_STREAMS")
|
||||
.inherit_env("ZISK_NUMBER_THREADS_WITNESS")
|
||||
.inherit_env("ZISK_MAX_WITNESS_STORED")
|
||||
.inherit_env("ZISK_PROVE_TIMEOUT_SEC"),
|
||||
.inherit_env("ERE_ZISK_SETUP_ON_INIT")
|
||||
.inherit_env("ERE_ZISK_PORT")
|
||||
.inherit_env("ERE_ZISK_UNLOCK_MAPPED_MEMORY")
|
||||
.inherit_env("ERE_ZISK_MINIMAL_MEMORY")
|
||||
.inherit_env("ERE_ZISK_PREALLOCATE")
|
||||
.inherit_env("ERE_ZISK_SHARED_TABLES")
|
||||
.inherit_env("ERE_ZISK_MAX_STREAMS")
|
||||
.inherit_env("ERE_ZISK_NUMBER_THREADS_WITNESS")
|
||||
.inherit_env("ERE_ZISK_MAX_WITNESS_STORED")
|
||||
.inherit_env("ERE_ZISK_START_SERVER_TIMEOUT_SEC")
|
||||
.inherit_env("ERE_ZISK_SHUTDOWN_SERVER_TIMEOUT_SEC")
|
||||
.inherit_env("ERE_ZISK_PROVE_TIMEOUT_SEC"),
|
||||
_ => cmd,
|
||||
};
|
||||
|
||||
@@ -272,7 +274,7 @@ impl ServerContainer {
|
||||
pub struct DockerizedzkVM {
|
||||
zkvm_kind: zkVMKind,
|
||||
program: SerializedProgram,
|
||||
resource: ProverResourceType,
|
||||
resource: ProverResource,
|
||||
container: RwLock<Option<ServerContainer>>,
|
||||
}
|
||||
|
||||
@@ -280,9 +282,9 @@ impl DockerizedzkVM {
|
||||
pub fn new(
|
||||
zkvm_kind: zkVMKind,
|
||||
program: SerializedProgram,
|
||||
resource: ProverResourceType,
|
||||
resource: ProverResource,
|
||||
) -> Result<Self, Error> {
|
||||
build_server_image(zkvm_kind, matches!(resource, ProverResourceType::Gpu))?;
|
||||
build_server_image(zkvm_kind, resource.is_gpu())?;
|
||||
|
||||
let container = ServerContainer::new(zkvm_kind, &program, &resource)?;
|
||||
|
||||
@@ -302,7 +304,7 @@ impl DockerizedzkVM {
|
||||
&self.program
|
||||
}
|
||||
|
||||
pub fn resource(&self) -> &ProverResourceType {
|
||||
pub fn resource(&self) -> &ProverResource {
|
||||
&self.resource
|
||||
}
|
||||
|
||||
@@ -424,14 +426,15 @@ async fn wait_until_healthy(endpoint: &Url, http_client: Client) -> Result<(), E
|
||||
}
|
||||
|
||||
fn block_on<T>(future: impl Future<Output = T>) -> T {
|
||||
static FALLBACK_RT: OnceLock<tokio::runtime::Runtime> = OnceLock::new();
|
||||
let handle = tokio::runtime::Handle::try_current().unwrap_or_else(|_| {
|
||||
FALLBACK_RT
|
||||
.get_or_init(|| tokio::runtime::Runtime::new().expect("Failed to create runtime"))
|
||||
.handle()
|
||||
.clone()
|
||||
});
|
||||
tokio::task::block_in_place(|| handle.block_on(future))
|
||||
match tokio::runtime::Handle::try_current() {
|
||||
Ok(handle) => tokio::task::block_in_place(|| handle.block_on(future)),
|
||||
Err(_) => {
|
||||
static FALLBACK_RT: OnceLock<tokio::runtime::Runtime> = OnceLock::new();
|
||||
FALLBACK_RT
|
||||
.get_or_init(|| tokio::runtime::Runtime::new().expect("Failed to create runtime"))
|
||||
.block_on(future)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -445,7 +448,7 @@ mod test {
|
||||
use ere_test_utils::{
|
||||
host::*, io::serde::bincode::BincodeLegacy, program::basic::BasicProgram,
|
||||
};
|
||||
use ere_zkvm_interface::zkvm::{Input, ProofKind, ProverResourceType, zkVM};
|
||||
use ere_zkvm_interface::zkvm::{Input, ProofKind, ProverResource, zkVM};
|
||||
|
||||
fn zkvm(
|
||||
zkvm_kind: zkVMKind,
|
||||
@@ -453,7 +456,7 @@ mod test {
|
||||
program: &'static str,
|
||||
) -> DockerizedzkVM {
|
||||
let program = compile(zkvm_kind, compiler_kind, program).clone();
|
||||
DockerizedzkVM::new(zkvm_kind, program, ProverResourceType::Cpu).unwrap()
|
||||
DockerizedzkVM::new(zkvm_kind, program, ProverResource::Cpu).unwrap()
|
||||
}
|
||||
|
||||
macro_rules! test {
|
||||
|
||||
@@ -11,7 +11,6 @@ auto_impl.workspace = true
|
||||
bincode = { workspace = true, features = ["alloc", "serde"] }
|
||||
indexmap = { workspace = true, features = ["serde"] }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde-untagged.workspace = true
|
||||
strum = { workspace = true, features = ["derive"] }
|
||||
thiserror.workspace = true
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ mod resource;
|
||||
pub use error::CommonError;
|
||||
pub use proof::{Proof, ProofKind};
|
||||
pub use report::{ProgramExecutionReport, ProgramProvingReport};
|
||||
pub use resource::{NetworkProverConfig, ProverResourceType};
|
||||
pub use resource::{ProverResource, ProverResourceKind, RemoteProverConfig};
|
||||
|
||||
/// Input for the prover to execute/prove a guest program.
|
||||
#[derive(Clone, Debug, Default)]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::zkvm::ProofKind;
|
||||
use crate::zkvm::{ProofKind, resource::ProverResourceKind};
|
||||
use std::{
|
||||
io,
|
||||
path::Path,
|
||||
@@ -51,6 +51,12 @@ pub enum CommonError {
|
||||
#[error("Unsupported input: {0}")]
|
||||
UnsupportedInput(String),
|
||||
|
||||
#[error("Unsupported prover resource kind {unsupported:?}, expect one of {supported:?}")]
|
||||
UnsupportedProverResourceKind {
|
||||
unsupported: ProverResourceKind,
|
||||
supported: Vec<ProverResourceKind>,
|
||||
},
|
||||
|
||||
#[error("Unsupported proof kind {unsupported:?}, expect one of {supported:?}")]
|
||||
UnsupportedProofKind {
|
||||
unsupported: ProofKind,
|
||||
@@ -141,6 +147,16 @@ impl CommonError {
|
||||
Self::UnsupportedInput(reason.as_ref().to_string())
|
||||
}
|
||||
|
||||
pub fn unsupported_prover_resource_kind(
|
||||
unsupported: ProverResourceKind,
|
||||
supported: impl IntoIterator<Item = ProverResourceKind>,
|
||||
) -> Self {
|
||||
Self::UnsupportedProverResourceKind {
|
||||
unsupported,
|
||||
supported: supported.into_iter().collect(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unsupported_proof_kind(
|
||||
unsupported: ProofKind,
|
||||
supported: impl IntoIterator<Item = ProofKind>,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use serde::{Deserialize, Deserializer, Serialize, de::Unexpected};
|
||||
use serde_untagged::UntaggedEnumVisitor;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use strum::{Display, EnumDiscriminants, EnumIs, EnumIter, EnumString};
|
||||
|
||||
/// Configuration for network-based proving
|
||||
/// Configuration for remote proving
|
||||
#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "clap", derive(clap::Args))]
|
||||
pub struct NetworkProverConfig {
|
||||
/// The endpoint URL of the prover network service
|
||||
pub struct RemoteProverConfig {
|
||||
/// The endpoint URL of the remote prover
|
||||
#[cfg_attr(feature = "clap", arg(long))]
|
||||
pub endpoint: String,
|
||||
/// Optional API key for authentication
|
||||
@@ -14,7 +14,7 @@ pub struct NetworkProverConfig {
|
||||
}
|
||||
|
||||
#[cfg(feature = "clap")]
|
||||
impl NetworkProverConfig {
|
||||
impl RemoteProverConfig {
|
||||
pub fn to_args(&self) -> Vec<&str> {
|
||||
core::iter::once(["--endpoint", self.endpoint.as_str()])
|
||||
.chain(self.api_key.as_deref().map(|val| ["--api-key", val]))
|
||||
@@ -24,18 +24,35 @@ impl NetworkProverConfig {
|
||||
}
|
||||
|
||||
/// ResourceType specifies what resource will be used to create the proofs.
|
||||
#[derive(Debug, Clone, Default, PartialEq, Eq)]
|
||||
#[derive(
|
||||
Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, EnumDiscriminants, EnumIs,
|
||||
)]
|
||||
#[strum_discriminants(
|
||||
name(ProverResourceKind),
|
||||
derive(Display, EnumString, EnumIter, Hash),
|
||||
strum(serialize_all = "lowercase")
|
||||
)]
|
||||
#[cfg_attr(feature = "clap", derive(clap::Subcommand))]
|
||||
pub enum ProverResourceType {
|
||||
#[serde(tag = "kind", rename_all = "lowercase")]
|
||||
pub enum ProverResource {
|
||||
#[default]
|
||||
Cpu,
|
||||
Gpu,
|
||||
/// Use a remote prover network
|
||||
Network(NetworkProverConfig),
|
||||
/// Official proving network
|
||||
Network(RemoteProverConfig),
|
||||
/// Self-hosted proving cluster
|
||||
Cluster(RemoteProverConfig),
|
||||
}
|
||||
|
||||
impl ProverResource {
|
||||
/// Returns [`ProverResourceKind`].
|
||||
pub fn kind(&self) -> ProverResourceKind {
|
||||
self.into()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "clap")]
|
||||
impl ProverResourceType {
|
||||
impl ProverResource {
|
||||
pub fn to_args(&self) -> Vec<&str> {
|
||||
match self {
|
||||
Self::Cpu => vec!["cpu"],
|
||||
@@ -43,51 +60,22 @@ impl ProverResourceType {
|
||||
Self::Network(config) => core::iter::once("network")
|
||||
.chain(config.to_args())
|
||||
.collect(),
|
||||
Self::Cluster(config) => core::iter::once("cluster")
|
||||
.chain(config.to_args())
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for ProverResourceType {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
match self {
|
||||
Self::Cpu => "cpu".serialize(serializer),
|
||||
Self::Gpu => "gpu".serialize(serializer),
|
||||
Self::Network(config) => config.serialize(serializer),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for ProverResourceType {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
UntaggedEnumVisitor::new()
|
||||
.string(|resource| match resource {
|
||||
"cpu" => Ok(Self::Cpu),
|
||||
"gpu" => Ok(Self::Gpu),
|
||||
_ => Err(serde::de::Error::invalid_value(
|
||||
Unexpected::Str(resource),
|
||||
&r#""cpu" or "gpu""#,
|
||||
)),
|
||||
})
|
||||
.map(|map| map.deserialize().map(Self::Network))
|
||||
.deserialize(deserializer)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::zkvm::resource::ProverResourceType;
|
||||
use crate::zkvm::resource::ProverResource;
|
||||
use core::fmt::Debug;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct Config {
|
||||
resources: Vec<ProverResourceType>,
|
||||
resources: Vec<ProverResource>,
|
||||
}
|
||||
|
||||
fn test_round_trip<'de, SE: Debug, DE: Debug>(
|
||||
@@ -101,7 +89,20 @@ mod test {
|
||||
#[test]
|
||||
fn test_round_trip_toml() {
|
||||
const TOML: &str = r#"
|
||||
resources = ["cpu", "gpu", { endpoint = "http://localhost:3000" }]
|
||||
[[resources]]
|
||||
kind = "cpu"
|
||||
|
||||
[[resources]]
|
||||
kind = "gpu"
|
||||
|
||||
[[resources]]
|
||||
kind = "network"
|
||||
endpoint = "http://localhost:3000"
|
||||
api_key = "my_api_key"
|
||||
|
||||
[[resources]]
|
||||
kind = "cluster"
|
||||
endpoint = "http://localhost:3000"
|
||||
"#;
|
||||
test_round_trip(TOML, toml::to_string, toml::from_str);
|
||||
}
|
||||
@@ -110,9 +111,13 @@ resources = ["cpu", "gpu", { endpoint = "http://localhost:3000" }]
|
||||
fn test_round_trip_yaml() {
|
||||
const YAML: &str = r#"
|
||||
resources:
|
||||
- cpu
|
||||
- gpu
|
||||
- endpoint: http://localhost:3000
|
||||
- kind: cpu
|
||||
- kind: gpu
|
||||
- kind: network
|
||||
endpoint: http://localhost:3000
|
||||
api_key: my_api_key
|
||||
- kind: cluster
|
||||
endpoint: http://localhost:3000
|
||||
api_key: null
|
||||
"#;
|
||||
test_round_trip(YAML, serde_yaml::to_string, serde_yaml::from_str);
|
||||
@@ -123,10 +128,20 @@ resources:
|
||||
const JSON: &str = r#"
|
||||
{
|
||||
"resources": [
|
||||
"cpu",
|
||||
"gpu",
|
||||
{
|
||||
"endpoint": "",
|
||||
"kind": "cpu"
|
||||
},
|
||||
{
|
||||
"kind": "gpu"
|
||||
},
|
||||
{
|
||||
"kind": "network",
|
||||
"endpoint": "http://localhost:3000",
|
||||
"api_key": "my_api_key"
|
||||
},
|
||||
{
|
||||
"kind": "cluster",
|
||||
"endpoint": "http://localhost:3000",
|
||||
"api_key": null
|
||||
}
|
||||
]
|
||||
|
||||
@@ -33,13 +33,14 @@
|
||||
//!
|
||||
//! # `zkVM` implementation
|
||||
//!
|
||||
//! ## Supported `ProverResourceType`
|
||||
//! ## Supported `ProverResource`
|
||||
//!
|
||||
//! | Resource | Supported |
|
||||
//! | --------- | :-------: |
|
||||
//! | `Cpu` | Yes |
|
||||
//! | `Gpu` | Yes |
|
||||
//! | `Network` | No |
|
||||
//! | `Cluster` | No |
|
||||
//!
|
||||
//! [`install_airbender_sdk.sh`]: https://github.com/eth-act/ere/blob/master/scripts/sdk_installers/install_airbender_sdk.sh
|
||||
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
use crate::{program::AirbenderProgram, zkvm::sdk::AirbenderSdk};
|
||||
use airbender_execution_utils::ProgramProof;
|
||||
use anyhow::bail;
|
||||
use ere_zkvm_interface::zkvm::{
|
||||
CommonError, Input, ProgramExecutionReport, ProgramProvingReport, Proof, ProofKind,
|
||||
ProverResourceType, PublicValues, zkVM, zkVMProgramDigest,
|
||||
use ere_zkvm_interface::{
|
||||
ProverResourceKind,
|
||||
zkvm::{
|
||||
CommonError, Input, ProgramExecutionReport, ProgramProvingReport, Proof, ProofKind,
|
||||
ProverResource, PublicValues, zkVM, zkVMProgramDigest,
|
||||
},
|
||||
};
|
||||
use std::time::Instant;
|
||||
|
||||
@@ -20,9 +23,14 @@ pub struct EreAirbender {
|
||||
}
|
||||
|
||||
impl EreAirbender {
|
||||
pub fn new(program: AirbenderProgram, resource: ProverResourceType) -> Result<Self, Error> {
|
||||
let gpu = matches!(resource, ProverResourceType::Gpu);
|
||||
let sdk = AirbenderSdk::new(program.bin(), gpu);
|
||||
pub fn new(program: AirbenderProgram, resource: ProverResource) -> Result<Self, Error> {
|
||||
if !matches!(resource, ProverResource::Cpu | ProverResource::Gpu) {
|
||||
Err(CommonError::unsupported_prover_resource_kind(
|
||||
resource.kind(),
|
||||
[ProverResourceKind::Cpu, ProverResourceKind::Gpu],
|
||||
))?;
|
||||
}
|
||||
let sdk = AirbenderSdk::new(program.bin(), resource.is_gpu());
|
||||
Ok(Self { sdk })
|
||||
}
|
||||
}
|
||||
@@ -30,7 +38,9 @@ impl EreAirbender {
|
||||
impl zkVM for EreAirbender {
|
||||
fn execute(&self, input: &Input) -> anyhow::Result<(PublicValues, ProgramExecutionReport)> {
|
||||
if input.proofs.is_some() {
|
||||
bail!(CommonError::unsupported_input("no dedicated proofs stream"))
|
||||
bail!(Error::from(CommonError::unsupported_input(
|
||||
"no dedicated proofs stream"
|
||||
)))
|
||||
}
|
||||
|
||||
let start = Instant::now();
|
||||
@@ -53,13 +63,15 @@ impl zkVM for EreAirbender {
|
||||
proof_kind: ProofKind,
|
||||
) -> anyhow::Result<(PublicValues, Proof, ProgramProvingReport)> {
|
||||
if input.proofs.is_some() {
|
||||
bail!(CommonError::unsupported_input("no dedicated proofs stream"))
|
||||
bail!(Error::from(CommonError::unsupported_input(
|
||||
"no dedicated proofs stream"
|
||||
)))
|
||||
}
|
||||
if proof_kind != ProofKind::Compressed {
|
||||
bail!(CommonError::unsupported_proof_kind(
|
||||
bail!(Error::from(CommonError::unsupported_proof_kind(
|
||||
proof_kind,
|
||||
[ProofKind::Compressed]
|
||||
))
|
||||
)))
|
||||
}
|
||||
let start = Instant::now();
|
||||
let (public_values, proof) = self.sdk.prove(input.stdin())?;
|
||||
@@ -77,10 +89,10 @@ impl zkVM for EreAirbender {
|
||||
|
||||
fn verify(&self, proof: &Proof) -> anyhow::Result<PublicValues> {
|
||||
let Proof::Compressed(proof) = proof else {
|
||||
bail!(CommonError::unsupported_proof_kind(
|
||||
bail!(Error::from(CommonError::unsupported_proof_kind(
|
||||
proof.kind(),
|
||||
[ProofKind::Compressed]
|
||||
))
|
||||
)))
|
||||
};
|
||||
|
||||
let (proof, _): (ProgramProof, _) =
|
||||
@@ -119,7 +131,7 @@ mod tests {
|
||||
};
|
||||
use ere_zkvm_interface::{
|
||||
compiler::Compiler,
|
||||
zkvm::{Input, ProofKind, ProverResourceType, zkVM},
|
||||
zkvm::{Input, ProofKind, ProverResource, zkVM},
|
||||
};
|
||||
use std::sync::OnceLock;
|
||||
|
||||
@@ -137,7 +149,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_execute() {
|
||||
let program = basic_program();
|
||||
let zkvm = EreAirbender::new(program, ProverResourceType::Cpu).unwrap();
|
||||
let zkvm = EreAirbender::new(program, ProverResource::Cpu).unwrap();
|
||||
|
||||
let test_case = BasicProgram::<BincodeLegacy>::valid_test_case().into_output_sha256();
|
||||
run_zkvm_execute(&zkvm, &test_case);
|
||||
@@ -146,7 +158,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_execute_invalid_test_case() {
|
||||
let program = basic_program();
|
||||
let zkvm = EreAirbender::new(program, ProverResourceType::Cpu).unwrap();
|
||||
let zkvm = EreAirbender::new(program, ProverResource::Cpu).unwrap();
|
||||
|
||||
for input in [
|
||||
Input::new(),
|
||||
@@ -159,7 +171,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_prove() {
|
||||
let program = basic_program();
|
||||
let zkvm = EreAirbender::new(program, ProverResourceType::Cpu).unwrap();
|
||||
let zkvm = EreAirbender::new(program, ProverResource::Cpu).unwrap();
|
||||
|
||||
let test_case = BasicProgram::<BincodeLegacy>::valid_test_case().into_output_sha256();
|
||||
run_zkvm_prove(&zkvm, &test_case);
|
||||
@@ -168,7 +180,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_prove_invalid_test_case() {
|
||||
let program = basic_program();
|
||||
let zkvm = EreAirbender::new(program, ProverResourceType::Cpu).unwrap();
|
||||
let zkvm = EreAirbender::new(program, ProverResource::Cpu).unwrap();
|
||||
|
||||
for input in [
|
||||
Input::new(),
|
||||
|
||||
@@ -62,7 +62,7 @@ mod tests {
|
||||
use ere_zkvm_interface::{
|
||||
Input,
|
||||
compiler::Compiler,
|
||||
zkvm::{ProverResourceType, zkVM},
|
||||
zkvm::{ProverResource, zkVM},
|
||||
};
|
||||
|
||||
#[test]
|
||||
@@ -76,7 +76,7 @@ mod tests {
|
||||
fn test_execute() {
|
||||
let guest_directory = testing_guest_directory("jolt", "stock_nightly_no_std");
|
||||
let program = RustRv64imac.compile(&guest_directory).unwrap();
|
||||
let zkvm = EreJolt::new(program, ProverResourceType::Cpu).unwrap();
|
||||
let zkvm = EreJolt::new(program, ProverResource::Cpu).unwrap();
|
||||
|
||||
zkvm.execute(&Input::new()).unwrap();
|
||||
}
|
||||
|
||||
@@ -21,13 +21,14 @@
|
||||
//!
|
||||
//! # `zkVM` implementation
|
||||
//!
|
||||
//! ## Supported `ProverResourceType`
|
||||
//! ## Supported `ProverResource`
|
||||
//!
|
||||
//! | Resource | Supported |
|
||||
//! | --------- | :-------: |
|
||||
//! | `Cpu` | Yes |
|
||||
//! | `Gpu` | No |
|
||||
//! | `Network` | No |
|
||||
//! | `Cluster` | No |
|
||||
//!
|
||||
//! [`install_jolt_sdk.sh`]: https://github.com/eth-act/ere/blob/master/scripts/sdk_installers/install_jolt_sdk.sh
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ use crate::{
|
||||
use anyhow::bail;
|
||||
use ere_zkvm_interface::zkvm::{
|
||||
CommonError, Input, ProgramExecutionReport, ProgramProvingReport, Proof, ProofKind,
|
||||
ProverResourceType, PublicValues, zkVM,
|
||||
ProverResource, ProverResourceKind, PublicValues, zkVM,
|
||||
};
|
||||
use jolt_ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
|
||||
use std::{env, io::Cursor, time::Instant};
|
||||
@@ -22,9 +22,12 @@ pub struct EreJolt {
|
||||
}
|
||||
|
||||
impl EreJolt {
|
||||
pub fn new(program: JoltProgram, resource: ProverResourceType) -> Result<Self, Error> {
|
||||
if !matches!(resource, ProverResourceType::Cpu) {
|
||||
panic!("Network or GPU proving not yet implemented for Miden. Use CPU resource type.");
|
||||
pub fn new(program: JoltProgram, resource: ProverResource) -> Result<Self, Error> {
|
||||
if !matches!(resource, ProverResource::Cpu) {
|
||||
Err(CommonError::unsupported_prover_resource_kind(
|
||||
resource.kind(),
|
||||
[ProverResourceKind::Cpu],
|
||||
))?;
|
||||
}
|
||||
let sdk = JoltSdk::new(program.elf(), JoltConfig::from_env());
|
||||
Ok(EreJolt { sdk })
|
||||
@@ -34,7 +37,9 @@ impl EreJolt {
|
||||
impl zkVM for EreJolt {
|
||||
fn execute(&self, input: &Input) -> anyhow::Result<(PublicValues, ProgramExecutionReport)> {
|
||||
if input.proofs.is_some() {
|
||||
bail!(CommonError::unsupported_input("no dedicated proofs stream"))
|
||||
bail!(Error::from(CommonError::unsupported_input(
|
||||
"no dedicated proofs stream"
|
||||
)))
|
||||
}
|
||||
|
||||
let start = Instant::now();
|
||||
@@ -57,13 +62,15 @@ impl zkVM for EreJolt {
|
||||
proof_kind: ProofKind,
|
||||
) -> anyhow::Result<(PublicValues, Proof, ProgramProvingReport)> {
|
||||
if input.proofs.is_some() {
|
||||
bail!(CommonError::unsupported_input("no dedicated proofs stream"))
|
||||
bail!(Error::from(CommonError::unsupported_input(
|
||||
"no dedicated proofs stream"
|
||||
)))
|
||||
}
|
||||
if proof_kind != ProofKind::Compressed {
|
||||
bail!(CommonError::unsupported_proof_kind(
|
||||
bail!(Error::from(CommonError::unsupported_proof_kind(
|
||||
proof_kind,
|
||||
[ProofKind::Compressed]
|
||||
))
|
||||
)))
|
||||
}
|
||||
|
||||
let start = Instant::now();
|
||||
@@ -84,10 +91,10 @@ impl zkVM for EreJolt {
|
||||
|
||||
fn verify(&self, proof: &Proof) -> anyhow::Result<PublicValues> {
|
||||
let Proof::Compressed(proof) = proof else {
|
||||
bail!(CommonError::unsupported_proof_kind(
|
||||
bail!(Error::from(CommonError::unsupported_proof_kind(
|
||||
proof.kind(),
|
||||
[ProofKind::Compressed]
|
||||
))
|
||||
)))
|
||||
};
|
||||
|
||||
let proof = JoltProof::deserialize_compressed(&mut Cursor::new(proof))
|
||||
@@ -118,7 +125,7 @@ mod tests {
|
||||
use ere_zkvm_interface::{
|
||||
Input,
|
||||
compiler::Compiler,
|
||||
zkvm::{ProofKind, ProverResourceType, zkVM},
|
||||
zkvm::{ProofKind, ProverResource, zkVM},
|
||||
};
|
||||
use std::sync::{Mutex, OnceLock};
|
||||
|
||||
@@ -141,7 +148,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_execute() {
|
||||
let program = basic_program();
|
||||
let zkvm = EreJolt::new(program, ProverResourceType::Cpu).unwrap();
|
||||
let zkvm = EreJolt::new(program, ProverResource::Cpu).unwrap();
|
||||
|
||||
let test_case = BasicProgram::<BincodeLegacy>::valid_test_case();
|
||||
run_zkvm_execute(&zkvm, &test_case);
|
||||
@@ -150,7 +157,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_execute_invalid_test_case() {
|
||||
let program = basic_program();
|
||||
let zkvm = EreJolt::new(program, ProverResourceType::Cpu).unwrap();
|
||||
let zkvm = EreJolt::new(program, ProverResource::Cpu).unwrap();
|
||||
|
||||
for input in [
|
||||
Input::new(),
|
||||
@@ -165,7 +172,7 @@ mod tests {
|
||||
let _guard = PROVE_LOCK.lock().unwrap();
|
||||
|
||||
let program = basic_program();
|
||||
let zkvm = EreJolt::new(program, ProverResourceType::Cpu).unwrap();
|
||||
let zkvm = EreJolt::new(program, ProverResource::Cpu).unwrap();
|
||||
|
||||
let test_case = BasicProgram::<BincodeLegacy>::valid_test_case();
|
||||
run_zkvm_prove(&zkvm, &test_case);
|
||||
@@ -176,7 +183,7 @@ mod tests {
|
||||
let _guard = PROVE_LOCK.lock().unwrap();
|
||||
|
||||
let program = basic_program();
|
||||
let zkvm = EreJolt::new(program, ProverResourceType::Cpu).unwrap();
|
||||
let zkvm = EreJolt::new(program, ProverResource::Cpu).unwrap();
|
||||
|
||||
for input in [
|
||||
Input::new(),
|
||||
|
||||
@@ -10,13 +10,14 @@
|
||||
//!
|
||||
//! # `zkVM` implementation
|
||||
//!
|
||||
//! ## Supported `ProverResourceType`
|
||||
//! ## Supported `ProverResource`
|
||||
//!
|
||||
//! | Resource | Supported |
|
||||
//! | --------- | :-------: |
|
||||
//! | `Cpu` | Yes |
|
||||
//! | `Gpu` | No |
|
||||
//! | `Network` | No |
|
||||
//! | `Cluster` | No |
|
||||
|
||||
#![cfg_attr(
|
||||
all(not(test), feature = "compiler", feature = "zkvm"),
|
||||
|
||||
@@ -2,7 +2,7 @@ use crate::program::{MidenProgram, MidenProgramInfo, MidenSerdeWrapper};
|
||||
use anyhow::bail;
|
||||
use ere_zkvm_interface::zkvm::{
|
||||
CommonError, Input, ProgramExecutionReport, ProgramProvingReport, Proof, ProofKind,
|
||||
ProverResourceType, PublicValues, zkVM, zkVMProgramDigest,
|
||||
ProverResource, ProverResourceKind, PublicValues, zkVM, zkVMProgramDigest,
|
||||
};
|
||||
use miden_core::{
|
||||
Program,
|
||||
@@ -38,9 +38,12 @@ pub struct EreMiden {
|
||||
}
|
||||
|
||||
impl EreMiden {
|
||||
pub fn new(program: MidenProgram, resource: ProverResourceType) -> Result<Self, Error> {
|
||||
if !matches!(resource, ProverResourceType::Cpu) {
|
||||
panic!("Network or GPU proving not yet implemented for Miden. Use CPU resource type.");
|
||||
pub fn new(program: MidenProgram, resource: ProverResource) -> Result<Self, Error> {
|
||||
if !matches!(resource, ProverResource::Cpu) {
|
||||
Err(CommonError::unsupported_prover_resource_kind(
|
||||
resource.kind(),
|
||||
[ProverResourceKind::Cpu],
|
||||
))?;
|
||||
}
|
||||
Ok(Self { program: program.0 })
|
||||
}
|
||||
@@ -58,7 +61,9 @@ impl EreMiden {
|
||||
impl zkVM for EreMiden {
|
||||
fn execute(&self, input: &Input) -> anyhow::Result<(PublicValues, ProgramExecutionReport)> {
|
||||
if input.proofs.is_some() {
|
||||
bail!(CommonError::unsupported_input("no dedicated proofs stream"))
|
||||
bail!(Error::from(CommonError::unsupported_input(
|
||||
"no dedicated proofs stream"
|
||||
)))
|
||||
}
|
||||
|
||||
let stack_inputs = StackInputs::default();
|
||||
@@ -92,13 +97,15 @@ impl zkVM for EreMiden {
|
||||
proof_kind: ProofKind,
|
||||
) -> anyhow::Result<(PublicValues, Proof, ProgramProvingReport)> {
|
||||
if input.proofs.is_some() {
|
||||
bail!(CommonError::unsupported_input("no dedicated proofs stream"))
|
||||
bail!(Error::from(CommonError::unsupported_input(
|
||||
"no dedicated proofs stream"
|
||||
)))
|
||||
}
|
||||
if proof_kind != ProofKind::Compressed {
|
||||
bail!(CommonError::unsupported_proof_kind(
|
||||
bail!(Error::from(CommonError::unsupported_proof_kind(
|
||||
proof_kind,
|
||||
[ProofKind::Compressed]
|
||||
))
|
||||
)))
|
||||
}
|
||||
|
||||
let stack_inputs = StackInputs::default();
|
||||
@@ -129,10 +136,10 @@ impl zkVM for EreMiden {
|
||||
|
||||
fn verify(&self, proof: &Proof) -> anyhow::Result<PublicValues> {
|
||||
let Proof::Compressed(proof) = proof else {
|
||||
bail!(CommonError::unsupported_proof_kind(
|
||||
bail!(Error::from(CommonError::unsupported_proof_kind(
|
||||
proof.kind(),
|
||||
[ProofKind::Compressed]
|
||||
))
|
||||
)))
|
||||
};
|
||||
|
||||
let program_info: ProgramInfo = self.program.clone().into();
|
||||
@@ -200,7 +207,7 @@ mod tests {
|
||||
use ere_zkvm_interface::{
|
||||
Input,
|
||||
compiler::Compiler,
|
||||
zkvm::{ProofKind, ProverResourceType, zkVM},
|
||||
zkvm::{ProofKind, ProverResource, zkVM},
|
||||
};
|
||||
|
||||
fn load_miden_program(guest_name: &str) -> MidenProgram {
|
||||
@@ -212,7 +219,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_prove_and_verify_add() {
|
||||
let program = load_miden_program("add");
|
||||
let zkvm = EreMiden::new(program, ProverResourceType::Cpu).unwrap();
|
||||
let zkvm = EreMiden::new(program, ProverResource::Cpu).unwrap();
|
||||
|
||||
let const_a = -Felt::ONE;
|
||||
let const_b = Felt::ONE / Felt::ONE.double();
|
||||
@@ -237,7 +244,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_prove_and_verify_fib() {
|
||||
let program = load_miden_program("fib");
|
||||
let zkvm = EreMiden::new(program, ProverResourceType::Cpu).unwrap();
|
||||
let zkvm = EreMiden::new(program, ProverResource::Cpu).unwrap();
|
||||
|
||||
let n_iterations = 50u32;
|
||||
let expected_fib = Felt::try_from(12_586_269_025u64).unwrap();
|
||||
@@ -261,7 +268,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_invalid_test_case() {
|
||||
let program = load_miden_program("add");
|
||||
let zkvm = EreMiden::new(program, ProverResourceType::Cpu).unwrap();
|
||||
let zkvm = EreMiden::new(program, ProverResource::Cpu).unwrap();
|
||||
|
||||
let empty_inputs = Input::new();
|
||||
assert!(zkvm.execute(&empty_inputs).is_err());
|
||||
|
||||
@@ -10,13 +10,14 @@
|
||||
//!
|
||||
//! # `zkVM` implementation
|
||||
//!
|
||||
//! ## Supported `ProverResourceType`
|
||||
//! ## Supported `ProverResource`
|
||||
//!
|
||||
//! | Resource | Supported |
|
||||
//! | --------- | :-------: |
|
||||
//! | `Cpu` | Yes |
|
||||
//! | `Gpu` | No |
|
||||
//! | `Network` | No |
|
||||
//! | `Cluster` | No |
|
||||
|
||||
#![cfg_attr(
|
||||
all(not(test), feature = "compiler", feature = "zkvm"),
|
||||
|
||||
@@ -2,7 +2,7 @@ use crate::program::NexusProgram;
|
||||
use anyhow::bail;
|
||||
use ere_zkvm_interface::zkvm::{
|
||||
CommonError, Input, ProgramExecutionReport, ProgramProvingReport, Proof, ProofKind,
|
||||
ProverResourceType, PublicValues, zkVM,
|
||||
ProverResource, ProverResourceKind, PublicValues, zkVM,
|
||||
};
|
||||
use nexus_core::nvm::{self, ElfFile, internals::LinearMemoryLayout};
|
||||
use nexus_sdk::{CheckedView, KnownExitCodes, Viewable};
|
||||
@@ -42,17 +42,20 @@ pub struct EreNexus {
|
||||
}
|
||||
|
||||
impl EreNexus {
|
||||
pub fn new(program: NexusProgram, resource: ProverResourceType) -> Result<Self, Error> {
|
||||
pub fn new(program: NexusProgram, resource: ProverResource) -> Result<Self, Error> {
|
||||
Self::with_extensions(program, resource, vec![])
|
||||
}
|
||||
|
||||
pub fn with_extensions(
|
||||
program: NexusProgram,
|
||||
resource: ProverResourceType,
|
||||
resource: ProverResource,
|
||||
extensions: Vec<NexusExtension>,
|
||||
) -> Result<Self, Error> {
|
||||
if !matches!(resource, ProverResourceType::Cpu) {
|
||||
panic!("Network or GPU proving not yet implemented for Nexus. Use CPU resource type.");
|
||||
if !matches!(resource, ProverResource::Cpu) {
|
||||
Err(CommonError::unsupported_prover_resource_kind(
|
||||
resource.kind(),
|
||||
[ProverResourceKind::Cpu],
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
@@ -65,7 +68,9 @@ impl EreNexus {
|
||||
impl zkVM for EreNexus {
|
||||
fn execute(&self, input: &Input) -> anyhow::Result<(PublicValues, ProgramExecutionReport)> {
|
||||
if input.proofs.is_some() {
|
||||
bail!(CommonError::unsupported_input("no dedicated proofs stream"))
|
||||
bail!(Error::from(CommonError::unsupported_input(
|
||||
"no dedicated proofs stream"
|
||||
)))
|
||||
}
|
||||
|
||||
let elf = ElfFile::from_bytes(self.program.elf()).map_err(Error::ParseElf)?;
|
||||
@@ -102,13 +107,15 @@ impl zkVM for EreNexus {
|
||||
proof_kind: ProofKind,
|
||||
) -> anyhow::Result<(PublicValues, Proof, ProgramProvingReport)> {
|
||||
if input.proofs.is_some() {
|
||||
bail!(CommonError::unsupported_input("no dedicated proofs stream"))
|
||||
bail!(Error::from(CommonError::unsupported_input(
|
||||
"no dedicated proofs stream"
|
||||
)))
|
||||
}
|
||||
if proof_kind != ProofKind::Compressed {
|
||||
bail!(CommonError::unsupported_proof_kind(
|
||||
bail!(Error::from(CommonError::unsupported_proof_kind(
|
||||
proof_kind,
|
||||
[ProofKind::Compressed]
|
||||
))
|
||||
)))
|
||||
}
|
||||
|
||||
let elf = ElfFile::from_bytes(self.program.elf()).map_err(Error::ParseElf)?;
|
||||
@@ -155,10 +162,10 @@ impl zkVM for EreNexus {
|
||||
|
||||
fn verify(&self, proof: &Proof) -> anyhow::Result<PublicValues> {
|
||||
let Proof::Compressed(proof) = proof else {
|
||||
bail!(CommonError::unsupported_proof_kind(
|
||||
bail!(Error::from(CommonError::unsupported_proof_kind(
|
||||
proof.kind(),
|
||||
[ProofKind::Compressed]
|
||||
))
|
||||
)))
|
||||
};
|
||||
|
||||
info!("Verifying proof...");
|
||||
@@ -244,7 +251,7 @@ mod tests {
|
||||
use ere_zkvm_interface::{
|
||||
Input,
|
||||
compiler::Compiler,
|
||||
zkvm::{ProofKind, ProverResourceType, zkVM},
|
||||
zkvm::{ProofKind, ProverResource, zkVM},
|
||||
};
|
||||
use std::sync::OnceLock;
|
||||
|
||||
@@ -262,7 +269,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_execute() {
|
||||
let program = basic_program();
|
||||
let zkvm = EreNexus::new(program, ProverResourceType::Cpu).unwrap();
|
||||
let zkvm = EreNexus::new(program, ProverResource::Cpu).unwrap();
|
||||
|
||||
let test_case = BasicProgram::<BincodeLegacy>::valid_test_case();
|
||||
run_zkvm_execute(&zkvm, &test_case);
|
||||
@@ -271,7 +278,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_execute_invalid_test_case() {
|
||||
let program = basic_program();
|
||||
let zkvm = EreNexus::new(program, ProverResourceType::Cpu).unwrap();
|
||||
let zkvm = EreNexus::new(program, ProverResource::Cpu).unwrap();
|
||||
|
||||
for input in [
|
||||
Input::new(),
|
||||
@@ -284,7 +291,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_prove() {
|
||||
let program = basic_program();
|
||||
let zkvm = EreNexus::new(program, ProverResourceType::Cpu).unwrap();
|
||||
let zkvm = EreNexus::new(program, ProverResource::Cpu).unwrap();
|
||||
|
||||
let test_case = BasicProgram::<BincodeLegacy>::valid_test_case();
|
||||
run_zkvm_prove(&zkvm, &test_case);
|
||||
@@ -293,7 +300,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_prove_invalid_test_case() {
|
||||
let program = basic_program();
|
||||
let zkvm = EreNexus::new(program, ProverResourceType::Cpu).unwrap();
|
||||
let zkvm = EreNexus::new(program, ProverResource::Cpu).unwrap();
|
||||
|
||||
for input in [
|
||||
Input::new(),
|
||||
|
||||
@@ -63,7 +63,7 @@ mod tests {
|
||||
use ere_zkvm_interface::{
|
||||
Input,
|
||||
compiler::Compiler,
|
||||
zkvm::{ProverResourceType, zkVM},
|
||||
zkvm::{ProverResource, zkVM},
|
||||
};
|
||||
|
||||
#[test]
|
||||
@@ -77,7 +77,7 @@ mod tests {
|
||||
fn test_execute() {
|
||||
let guest_directory = testing_guest_directory("openvm", "stock_nightly_no_std");
|
||||
let program = RustRv32ima.compile(&guest_directory).unwrap();
|
||||
let zkvm = EreOpenVM::new(program, ProverResourceType::Cpu).unwrap();
|
||||
let zkvm = EreOpenVM::new(program, ProverResource::Cpu).unwrap();
|
||||
|
||||
zkvm.execute(&Input::new()).unwrap();
|
||||
}
|
||||
|
||||
@@ -25,13 +25,14 @@
|
||||
//!
|
||||
//! # `zkVM` implementation
|
||||
//!
|
||||
//! ## Supported `ProverResourceType`
|
||||
//! ## Supported `ProverResource`
|
||||
//!
|
||||
//! | Resource | Supported |
|
||||
//! | --------- | :-------: |
|
||||
//! | `Cpu` | Yes |
|
||||
//! | `Gpu` | Yes |
|
||||
//! | `Network` | No |
|
||||
//! | `Cluster` | No |
|
||||
//!
|
||||
//! [`install_openvm_sdk.sh`]: https://github.com/eth-act/ere/blob/master/scripts/sdk_installers/install_openvm_sdk.sh
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ use crate::program::OpenVMProgram;
|
||||
use anyhow::bail;
|
||||
use ere_zkvm_interface::zkvm::{
|
||||
CommonError, Input, ProgramExecutionReport, ProgramProvingReport, Proof, ProofKind,
|
||||
ProverResourceType, PublicValues, zkVM, zkVMProgramDigest,
|
||||
ProverResource, ProverResourceKind, PublicValues, zkVM, zkVMProgramDigest,
|
||||
};
|
||||
use openvm_circuit::arch::instructions::exe::VmExe;
|
||||
use openvm_continuations::verifier::internal::types::VmStarkProof;
|
||||
@@ -31,22 +31,21 @@ pub struct EreOpenVM {
|
||||
agg_pk: AggProvingKey,
|
||||
agg_vk: AggVerifyingKey,
|
||||
app_commit: AppExecutionCommit,
|
||||
resource: ProverResourceType,
|
||||
resource: ProverResource,
|
||||
}
|
||||
|
||||
impl EreOpenVM {
|
||||
pub fn new(program: OpenVMProgram, resource: ProverResourceType) -> Result<Self, Error> {
|
||||
match resource {
|
||||
#[cfg(not(feature = "cuda"))]
|
||||
ProverResourceType::Gpu => {
|
||||
panic!("Feature `cuda` is disabled. Enable `cuda` to use GPU resource type")
|
||||
}
|
||||
ProverResourceType::Network(_) => {
|
||||
panic!(
|
||||
"Network proving not yet implemented for OpenVM. Use CPU or GPU resource type."
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
pub fn new(program: OpenVMProgram, resource: ProverResource) -> Result<Self, Error> {
|
||||
#[cfg(not(feature = "cuda"))]
|
||||
if resource.is_gpu() {
|
||||
return Err(Error::CudaFeatureDisabled);
|
||||
}
|
||||
|
||||
if !matches!(resource, ProverResource::Cpu | ProverResource::Gpu) {
|
||||
Err(CommonError::unsupported_prover_resource_kind(
|
||||
resource.kind(),
|
||||
[ProverResourceKind::Cpu, ProverResourceKind::Gpu],
|
||||
))?;
|
||||
}
|
||||
|
||||
let app_config = if let Some(value) = program.app_config() {
|
||||
@@ -124,7 +123,9 @@ impl EreOpenVM {
|
||||
impl zkVM for EreOpenVM {
|
||||
fn execute(&self, input: &Input) -> anyhow::Result<(PublicValues, ProgramExecutionReport)> {
|
||||
if input.proofs.is_some() {
|
||||
bail!(CommonError::unsupported_input("no dedicated proofs stream"))
|
||||
bail!(Error::from(CommonError::unsupported_input(
|
||||
"no dedicated proofs stream"
|
||||
)))
|
||||
}
|
||||
|
||||
let mut stdin = StdIn::default();
|
||||
@@ -151,13 +152,15 @@ impl zkVM for EreOpenVM {
|
||||
proof_kind: ProofKind,
|
||||
) -> anyhow::Result<(PublicValues, Proof, ProgramProvingReport)> {
|
||||
if input.proofs.is_some() {
|
||||
bail!(CommonError::unsupported_input("no dedicated proofs stream"))
|
||||
bail!(Error::from(CommonError::unsupported_input(
|
||||
"no dedicated proofs stream"
|
||||
)))
|
||||
}
|
||||
if proof_kind != ProofKind::Compressed {
|
||||
bail!(CommonError::unsupported_proof_kind(
|
||||
bail!(Error::from(CommonError::unsupported_proof_kind(
|
||||
proof_kind,
|
||||
[ProofKind::Compressed]
|
||||
))
|
||||
)))
|
||||
}
|
||||
|
||||
let mut stdin = StdIn::default();
|
||||
@@ -165,18 +168,15 @@ impl zkVM for EreOpenVM {
|
||||
|
||||
let now = std::time::Instant::now();
|
||||
let (proof, app_commit) = match self.resource {
|
||||
ProverResourceType::Cpu => self.cpu_sdk()?.prove(self.app_exe.clone(), stdin),
|
||||
ProverResource::Cpu => self.cpu_sdk()?.prove(self.app_exe.clone(), stdin),
|
||||
#[cfg(feature = "cuda")]
|
||||
ProverResourceType::Gpu => self.gpu_sdk()?.prove(self.app_exe.clone(), stdin),
|
||||
ProverResource::Gpu => self.gpu_sdk()?.prove(self.app_exe.clone(), stdin),
|
||||
#[cfg(not(feature = "cuda"))]
|
||||
ProverResourceType::Gpu => {
|
||||
panic!("Feature `cuda` is disabled. Enable `cuda` to use GPU resource type")
|
||||
}
|
||||
ProverResourceType::Network(_) => {
|
||||
panic!(
|
||||
"Network proving not yet implemented for OpenVM. Use CPU or GPU resource type."
|
||||
);
|
||||
}
|
||||
ProverResource::Gpu => bail!(Error::CudaFeatureDisabled),
|
||||
_ => bail!(Error::from(CommonError::unsupported_prover_resource_kind(
|
||||
self.resource.kind(),
|
||||
[ProverResourceKind::Cpu, ProverResourceKind::Gpu],
|
||||
))),
|
||||
}
|
||||
.map_err(Error::Prove)?;
|
||||
let elapsed = now.elapsed();
|
||||
@@ -205,10 +205,10 @@ impl zkVM for EreOpenVM {
|
||||
|
||||
fn verify(&self, proof: &Proof) -> anyhow::Result<PublicValues> {
|
||||
let Proof::Compressed(proof) = proof else {
|
||||
bail!(CommonError::unsupported_proof_kind(
|
||||
bail!(Error::from(CommonError::unsupported_proof_kind(
|
||||
proof.kind(),
|
||||
[ProofKind::Compressed]
|
||||
))
|
||||
)))
|
||||
};
|
||||
|
||||
let proof = VmStarkProof::<SC>::decode(&mut proof.as_slice())
|
||||
@@ -265,7 +265,7 @@ mod tests {
|
||||
};
|
||||
use ere_zkvm_interface::{
|
||||
compiler::Compiler,
|
||||
zkvm::{Input, ProofKind, ProverResourceType, zkVM},
|
||||
zkvm::{Input, ProofKind, ProverResource, zkVM},
|
||||
};
|
||||
use std::sync::OnceLock;
|
||||
|
||||
@@ -283,7 +283,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_execute() {
|
||||
let program = basic_program();
|
||||
let zkvm = EreOpenVM::new(program, ProverResourceType::Cpu).unwrap();
|
||||
let zkvm = EreOpenVM::new(program, ProverResource::Cpu).unwrap();
|
||||
|
||||
let test_case = BasicProgram::<BincodeLegacy>::valid_test_case().into_output_sha256();
|
||||
run_zkvm_execute(&zkvm, &test_case);
|
||||
@@ -292,7 +292,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_execute_invalid_test_case() {
|
||||
let program = basic_program();
|
||||
let zkvm = EreOpenVM::new(program, ProverResourceType::Cpu).unwrap();
|
||||
let zkvm = EreOpenVM::new(program, ProverResource::Cpu).unwrap();
|
||||
|
||||
for input in [
|
||||
Input::new(),
|
||||
@@ -305,7 +305,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_prove() {
|
||||
let program = basic_program();
|
||||
let zkvm = EreOpenVM::new(program, ProverResourceType::Cpu).unwrap();
|
||||
let zkvm = EreOpenVM::new(program, ProverResource::Cpu).unwrap();
|
||||
|
||||
let test_case = BasicProgram::<BincodeLegacy>::valid_test_case().into_output_sha256();
|
||||
run_zkvm_prove(&zkvm, &test_case);
|
||||
@@ -314,7 +314,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_prove_invalid_test_case() {
|
||||
let program = basic_program();
|
||||
let zkvm = EreOpenVM::new(program, ProverResourceType::Cpu).unwrap();
|
||||
let zkvm = EreOpenVM::new(program, ProverResource::Cpu).unwrap();
|
||||
|
||||
for input in [
|
||||
Input::new(),
|
||||
|
||||
@@ -8,6 +8,9 @@ pub enum Error {
|
||||
CommonError(#[from] CommonError),
|
||||
|
||||
// Common
|
||||
#[error("Enable `cuda` feature to enable `ProverResource::Gpu`")]
|
||||
CudaFeatureDisabled,
|
||||
|
||||
#[error("Invalid AppConfig: {0}")]
|
||||
InvalidAppConfig(toml::de::Error),
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ mod tests {
|
||||
use ere_zkvm_interface::{
|
||||
Input,
|
||||
compiler::Compiler,
|
||||
zkvm::{ProverResourceType, zkVM},
|
||||
zkvm::{ProverResource, zkVM},
|
||||
};
|
||||
|
||||
#[test]
|
||||
@@ -68,7 +68,7 @@ mod tests {
|
||||
fn test_execute() {
|
||||
let guest_directory = testing_guest_directory("pico", "stock_nightly_no_std");
|
||||
let program = RustRv32ima.compile(&guest_directory).unwrap();
|
||||
let zkvm = ErePico::new(program, ProverResourceType::Cpu).unwrap();
|
||||
let zkvm = ErePico::new(program, ProverResource::Cpu).unwrap();
|
||||
|
||||
zkvm.execute(&Input::new()).unwrap();
|
||||
}
|
||||
|
||||
@@ -20,13 +20,14 @@
|
||||
//!
|
||||
//! # `zkVM` implementation
|
||||
//!
|
||||
//! ## Supported `ProverResourceType`
|
||||
//! ## Supported `ProverResource`
|
||||
//!
|
||||
//! | Resource | Supported |
|
||||
//! | --------- | :-------: |
|
||||
//! | `Cpu` | Yes |
|
||||
//! | `Gpu` | No |
|
||||
//! | `Network` | No |
|
||||
//! | `Cluster` | No |
|
||||
//!
|
||||
//! [`install_pico_sdk.sh`]: https://github.com/eth-act/ere/blob/master/scripts/sdk_installers/install_pico_sdk.sh
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ use crate::{
|
||||
use anyhow::bail;
|
||||
use ere_zkvm_interface::zkvm::{
|
||||
CommonError, Input, ProgramExecutionReport, ProgramProvingReport, Proof, ProofKind,
|
||||
ProverResourceType, PublicValues, zkVM, zkVMProgramDigest,
|
||||
ProverResource, ProverResourceKind, PublicValues, zkVM, zkVMProgramDigest,
|
||||
};
|
||||
use pico_p3_field::PrimeField32;
|
||||
use pico_vm::emulator::stdin::EmulatorStdinBuilder;
|
||||
@@ -31,9 +31,12 @@ pub struct ErePico {
|
||||
}
|
||||
|
||||
impl ErePico {
|
||||
pub fn new(program: PicoProgram, resource: ProverResourceType) -> Result<Self, Error> {
|
||||
if !matches!(resource, ProverResourceType::Cpu) {
|
||||
panic!("Network or GPU proving not yet implemented for Pico. Use CPU resource type.");
|
||||
pub fn new(program: PicoProgram, resource: ProverResource) -> Result<Self, Error> {
|
||||
if !matches!(resource, ProverResource::Cpu) {
|
||||
Err(CommonError::unsupported_prover_resource_kind(
|
||||
resource.kind(),
|
||||
[ProverResourceKind::Cpu],
|
||||
))?;
|
||||
}
|
||||
Ok(ErePico { program })
|
||||
}
|
||||
@@ -46,7 +49,9 @@ impl ErePico {
|
||||
impl zkVM for ErePico {
|
||||
fn execute(&self, input: &Input) -> anyhow::Result<(PublicValues, ProgramExecutionReport)> {
|
||||
if input.proofs.is_some() {
|
||||
bail!(CommonError::unsupported_input("no dedicated proofs stream"))
|
||||
bail!(Error::from(CommonError::unsupported_input(
|
||||
"no dedicated proofs stream"
|
||||
)))
|
||||
}
|
||||
|
||||
let mut stdin = EmulatorStdinBuilder::default();
|
||||
@@ -77,13 +82,15 @@ impl zkVM for ErePico {
|
||||
proof_kind: ProofKind,
|
||||
) -> anyhow::Result<(PublicValues, Proof, ProgramProvingReport)> {
|
||||
if input.proofs.is_some() {
|
||||
bail!(CommonError::unsupported_input("no dedicated proofs stream"))
|
||||
bail!(Error::from(CommonError::unsupported_input(
|
||||
"no dedicated proofs stream"
|
||||
)))
|
||||
}
|
||||
if proof_kind != ProofKind::Compressed {
|
||||
bail!(CommonError::unsupported_proof_kind(
|
||||
bail!(Error::from(CommonError::unsupported_proof_kind(
|
||||
proof_kind,
|
||||
[ProofKind::Compressed]
|
||||
))
|
||||
)))
|
||||
}
|
||||
|
||||
let mut stdin = EmulatorStdinBuilder::default();
|
||||
@@ -116,10 +123,10 @@ impl zkVM for ErePico {
|
||||
|
||||
fn verify(&self, proof: &Proof) -> anyhow::Result<PublicValues> {
|
||||
let Proof::Compressed(proof) = proof else {
|
||||
bail!(CommonError::unsupported_proof_kind(
|
||||
bail!(Error::from(CommonError::unsupported_proof_kind(
|
||||
proof.kind(),
|
||||
[ProofKind::Compressed]
|
||||
))
|
||||
)))
|
||||
};
|
||||
|
||||
let client = self.client();
|
||||
@@ -195,7 +202,7 @@ mod tests {
|
||||
};
|
||||
use ere_zkvm_interface::{
|
||||
compiler::Compiler,
|
||||
zkvm::{Input, ProofKind, ProverResourceType, zkVM},
|
||||
zkvm::{Input, ProofKind, ProverResource, zkVM},
|
||||
};
|
||||
use std::sync::OnceLock;
|
||||
|
||||
@@ -213,7 +220,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_execute() {
|
||||
let program = basic_program();
|
||||
let zkvm = ErePico::new(program, ProverResourceType::Cpu).unwrap();
|
||||
let zkvm = ErePico::new(program, ProverResource::Cpu).unwrap();
|
||||
|
||||
let test_case = BasicProgram::<BincodeLegacy>::valid_test_case();
|
||||
run_zkvm_execute(&zkvm, &test_case);
|
||||
@@ -222,7 +229,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_execute_invalid_test_case() {
|
||||
let program = basic_program();
|
||||
let zkvm = ErePico::new(program, ProverResourceType::Cpu).unwrap();
|
||||
let zkvm = ErePico::new(program, ProverResource::Cpu).unwrap();
|
||||
|
||||
for input in [
|
||||
Input::new(),
|
||||
@@ -235,7 +242,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_prove() {
|
||||
let program = basic_program();
|
||||
let zkvm = ErePico::new(program, ProverResourceType::Cpu).unwrap();
|
||||
let zkvm = ErePico::new(program, ProverResource::Cpu).unwrap();
|
||||
|
||||
let test_case = BasicProgram::<BincodeLegacy>::valid_test_case();
|
||||
run_zkvm_prove(&zkvm, &test_case);
|
||||
@@ -244,7 +251,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_prove_invalid_test_case() {
|
||||
let program = basic_program();
|
||||
let zkvm = ErePico::new(program, ProverResourceType::Cpu).unwrap();
|
||||
let zkvm = ErePico::new(program, ProverResource::Cpu).unwrap();
|
||||
|
||||
for input in [
|
||||
Input::new(),
|
||||
|
||||
@@ -66,7 +66,7 @@ mod tests {
|
||||
use ere_zkvm_interface::{
|
||||
Input,
|
||||
compiler::Compiler,
|
||||
zkvm::{ProverResourceType, zkVM},
|
||||
zkvm::{ProverResource, zkVM},
|
||||
};
|
||||
|
||||
#[test]
|
||||
@@ -80,7 +80,7 @@ mod tests {
|
||||
fn test_execute() {
|
||||
let guest_directory = testing_guest_directory("risc0", "stock_nightly_no_std");
|
||||
let program = RustRv32ima.compile(&guest_directory).unwrap();
|
||||
let zkvm = EreRisc0::new(program, ProverResourceType::Cpu).unwrap();
|
||||
let zkvm = EreRisc0::new(program, ProverResource::Cpu).unwrap();
|
||||
|
||||
zkvm.execute(&Input::new()).unwrap();
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
//!
|
||||
//! - [`rzup`]
|
||||
//! - Installation via `rzup install`
|
||||
//! - `r0vm-cuda` - Used by `zkVM::prove` if `ProverResourceType::Gpu` is
|
||||
//! - `r0vm-cuda` - Used by `zkVM::prove` if `ProverResource::Gpu` is
|
||||
//! selected
|
||||
//! - `docker` - Used by `zkVM::prove` if `ProofKind::Groth16` is selected
|
||||
//!
|
||||
@@ -32,13 +32,14 @@
|
||||
//!
|
||||
//! # `zkVM` implementation
|
||||
//!
|
||||
//! ## Supported `ProverResourceType`
|
||||
//! ## Supported `ProverResource`
|
||||
//!
|
||||
//! | Resource | Supported |
|
||||
//! | --------- | :-------: |
|
||||
//! | `Cpu` | Yes |
|
||||
//! | `Gpu` | Yes |
|
||||
//! | `Network` | No |
|
||||
//! | `Cluster` | No |
|
||||
//!
|
||||
//! [`install_risc0_sdk.sh`]: https://github.com/eth-act/ere/blob/master/scripts/sdk_installers/install_risc0_sdk.sh
|
||||
//! [`rzup`]: https://risczero.com/install
|
||||
|
||||
@@ -2,7 +2,7 @@ use crate::program::Risc0Program;
|
||||
use anyhow::bail;
|
||||
use ere_zkvm_interface::zkvm::{
|
||||
CommonError, Input, ProgramExecutionReport, ProgramProvingReport, Proof, ProofKind,
|
||||
ProverResourceType, PublicValues, zkVM, zkVMProgramDigest,
|
||||
ProverResource, ProverResourceKind, PublicValues, zkVM, zkVMProgramDigest,
|
||||
};
|
||||
use risc0_zkvm::{
|
||||
AssumptionReceipt, DEFAULT_MAX_PO2, DefaultProver, Digest, ExecutorEnv, ExternalProver,
|
||||
@@ -44,33 +44,41 @@ const KECCAK_PO2_RANGE: RangeInclusive<usize> = 14..=18;
|
||||
|
||||
pub struct EreRisc0 {
|
||||
program: Risc0Program,
|
||||
resource: ProverResourceType,
|
||||
resource: ProverResource,
|
||||
segment_po2: usize,
|
||||
keccak_po2: usize,
|
||||
}
|
||||
|
||||
impl EreRisc0 {
|
||||
pub fn new(program: Risc0Program, resource: ProverResourceType) -> Result<Self, Error> {
|
||||
if matches!(resource, ProverResourceType::Network(_)) {
|
||||
panic!(
|
||||
"Network proving not yet implemented for RISC Zero. Use CPU or GPU resource type."
|
||||
);
|
||||
pub fn new(program: Risc0Program, resource: ProverResource) -> Result<Self, Error> {
|
||||
if !matches!(resource, ProverResource::Cpu | ProverResource::Gpu) {
|
||||
Err(CommonError::unsupported_prover_resource_kind(
|
||||
resource.kind(),
|
||||
[ProverResourceKind::Cpu, ProverResourceKind::Gpu],
|
||||
))?;
|
||||
}
|
||||
|
||||
let [segment_po2, keccak_po2] = [
|
||||
("RISC0_SEGMENT_PO2", DEFAULT_SEGMENT_PO2, SEGMENT_PO2_RANGE),
|
||||
("RISC0_KECCAK_PO2", DEFAULT_KECCAK_PO2, KECCAK_PO2_RANGE),
|
||||
]
|
||||
.map(|(key, default, range)| {
|
||||
let val = env::var(key)
|
||||
.ok()
|
||||
.and_then(|po2| po2.parse::<usize>().ok())
|
||||
.unwrap_or(default);
|
||||
if !range.contains(&val) {
|
||||
panic!("Unsupported po2 value {val} of {key}, expected in range {range:?}")
|
||||
let parse_env = |key: &str, default: usize, range: RangeInclusive<usize>| {
|
||||
let Ok(val) = env::var(key) else {
|
||||
return Ok(default);
|
||||
};
|
||||
|
||||
match val.parse() {
|
||||
Ok(val) if range.contains(&val) => Ok(val),
|
||||
_ => Err(Error::UnsupportedPo2Value {
|
||||
key: key.to_string(),
|
||||
val,
|
||||
range,
|
||||
}),
|
||||
}
|
||||
val
|
||||
});
|
||||
};
|
||||
|
||||
let segment_po2 = parse_env(
|
||||
"ERE_RISC0_SEGMENT_PO2",
|
||||
DEFAULT_SEGMENT_PO2,
|
||||
SEGMENT_PO2_RANGE,
|
||||
)?;
|
||||
let keccak_po2 = parse_env("ERE_RISC0_KECCAK_PO2", DEFAULT_KECCAK_PO2, KECCAK_PO2_RANGE)?;
|
||||
|
||||
Ok(Self {
|
||||
program,
|
||||
@@ -112,8 +120,8 @@ impl zkVM for EreRisc0 {
|
||||
let env = self.input_to_env(input)?;
|
||||
|
||||
let prover = match self.resource {
|
||||
ProverResourceType::Cpu => Rc::new(ExternalProver::new("ipc", "r0vm")),
|
||||
ProverResourceType::Gpu => {
|
||||
ProverResource::Cpu => Rc::new(ExternalProver::new("ipc", "r0vm")),
|
||||
ProverResource::Gpu => {
|
||||
if cfg!(feature = "metal") {
|
||||
// When `metal` is enabled, we use the `LocalProver` to do
|
||||
// proving. but it's not public so we use `default_prover`
|
||||
@@ -127,11 +135,10 @@ impl zkVM for EreRisc0 {
|
||||
Rc::new(DefaultProver::new("r0vm-cuda").map_err(Error::InitializeCudaProver)?)
|
||||
}
|
||||
}
|
||||
ProverResourceType::Network(_) => {
|
||||
panic!(
|
||||
"Network proving not yet implemented for RISC Zero. Use CPU or GPU resource type."
|
||||
);
|
||||
}
|
||||
_ => bail!(Error::from(CommonError::unsupported_prover_resource_kind(
|
||||
self.resource.kind(),
|
||||
[ProverResourceKind::Cpu, ProverResourceKind::Gpu],
|
||||
))),
|
||||
};
|
||||
|
||||
let opts = match proof_kind {
|
||||
@@ -234,7 +241,7 @@ mod tests {
|
||||
use ere_zkvm_interface::{
|
||||
Input,
|
||||
compiler::Compiler,
|
||||
zkvm::{ProofKind, ProverResourceType, zkVM},
|
||||
zkvm::{ProofKind, ProverResource, zkVM},
|
||||
};
|
||||
use std::sync::OnceLock;
|
||||
|
||||
@@ -252,7 +259,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_execute() {
|
||||
let program = basic_program();
|
||||
let zkvm = EreRisc0::new(program, ProverResourceType::Cpu).unwrap();
|
||||
let zkvm = EreRisc0::new(program, ProverResource::Cpu).unwrap();
|
||||
|
||||
let test_case = BasicProgram::<BincodeLegacy>::valid_test_case();
|
||||
run_zkvm_execute(&zkvm, &test_case);
|
||||
@@ -261,7 +268,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_execute_invalid_test_case() {
|
||||
let program = basic_program();
|
||||
let zkvm = EreRisc0::new(program, ProverResourceType::Cpu).unwrap();
|
||||
let zkvm = EreRisc0::new(program, ProverResource::Cpu).unwrap();
|
||||
|
||||
for input in [
|
||||
Input::new(),
|
||||
@@ -274,7 +281,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_prove() {
|
||||
let program = basic_program();
|
||||
let zkvm = EreRisc0::new(program, ProverResourceType::Cpu).unwrap();
|
||||
let zkvm = EreRisc0::new(program, ProverResource::Cpu).unwrap();
|
||||
|
||||
let test_case = BasicProgram::<BincodeLegacy>::valid_test_case();
|
||||
run_zkvm_prove(&zkvm, &test_case);
|
||||
@@ -283,7 +290,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_prove_invalid_test_case() {
|
||||
let program = basic_program();
|
||||
let zkvm = EreRisc0::new(program, ProverResourceType::Cpu).unwrap();
|
||||
let zkvm = EreRisc0::new(program, ProverResource::Cpu).unwrap();
|
||||
|
||||
for input in [
|
||||
Input::new(),
|
||||
@@ -300,7 +307,7 @@ mod tests {
|
||||
.unwrap();
|
||||
|
||||
for i in 1..=16_u32 {
|
||||
let zkvm = EreRisc0::new(program.clone(), ProverResourceType::Cpu).unwrap();
|
||||
let zkvm = EreRisc0::new(program.clone(), ProverResource::Cpu).unwrap();
|
||||
|
||||
let input = Input::new().with_stdin(i.to_le_bytes().to_vec());
|
||||
|
||||
|
||||
@@ -1,12 +1,23 @@
|
||||
use ere_zkvm_interface::zkvm::ProofKind;
|
||||
use core::ops::RangeInclusive;
|
||||
use ere_zkvm_interface::zkvm::{CommonError, ProofKind};
|
||||
use risc0_zkp::verify::VerificationError;
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum Error {
|
||||
#[error(transparent)]
|
||||
CommonError(#[from] CommonError),
|
||||
|
||||
#[error("Deserialize proofs in Input failed: {0:?}")]
|
||||
DeserializeInputProofs(bincode::error::DecodeError),
|
||||
|
||||
#[error("Unsupported power of 2 value {val} of {key}, expected in range {range:?}")]
|
||||
UnsupportedPo2Value {
|
||||
key: String,
|
||||
val: String,
|
||||
range: RangeInclusive<usize>,
|
||||
},
|
||||
|
||||
// Execute
|
||||
#[error("Failed to build `ExecutorEnv`: {0}")]
|
||||
BuildExecutorEnv(anyhow::Error),
|
||||
|
||||
@@ -54,7 +54,7 @@ mod tests {
|
||||
use ere_zkvm_interface::{
|
||||
Input,
|
||||
compiler::Compiler,
|
||||
zkvm::{ProverResourceType, zkVM},
|
||||
zkvm::{ProverResource, zkVM},
|
||||
};
|
||||
|
||||
#[test]
|
||||
@@ -68,7 +68,7 @@ mod tests {
|
||||
fn test_execute() {
|
||||
let guest_directory = testing_guest_directory("sp1", "stock_nightly_no_std");
|
||||
let program = RustRv32ima.compile(&guest_directory).unwrap();
|
||||
let zkvm = EreSP1::new(program, ProverResourceType::Cpu).unwrap();
|
||||
let zkvm = EreSP1::new(program, ProverResource::Cpu).unwrap();
|
||||
|
||||
zkvm.execute(&Input::new()).unwrap();
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
//!
|
||||
//! ## `zkVM` requirements
|
||||
//!
|
||||
//! - `docker` - Used by `zkVM::prove` if `ProverResourceType::Gpu` is selected
|
||||
//! - `docker` - Used by `zkVM::prove` if `ProverResource::Gpu` is selected
|
||||
//!
|
||||
//! # `Compiler` implementation
|
||||
//!
|
||||
@@ -25,13 +25,14 @@
|
||||
//!
|
||||
//! # `zkVM` implementation
|
||||
//!
|
||||
//! ## Supported `ProverResourceType`
|
||||
//! ## Supported `ProverResource`
|
||||
//!
|
||||
//! | Resource | Supported |
|
||||
//! | --------- | :-------: |
|
||||
//! | `Cpu` | Yes |
|
||||
//! | `Gpu` | Yes |
|
||||
//! | `Network` | Yes |
|
||||
//! | `Cluster` | No |
|
||||
//!
|
||||
//! [`install_sp1_sdk.sh`]: https://github.com/eth-act/ere/blob/master/scripts/sdk_installers/install_sp1_sdk.sh
|
||||
//! [`sp1up`]: https://sp1up.succinct.xyz
|
||||
|
||||
@@ -2,7 +2,7 @@ use crate::{program::SP1Program, zkvm::sdk::Prover};
|
||||
use anyhow::bail;
|
||||
use ere_zkvm_interface::zkvm::{
|
||||
CommonError, Input, ProgramExecutionReport, ProgramProvingReport, Proof, ProofKind,
|
||||
ProverResourceType, PublicValues, zkVM, zkVMProgramDigest,
|
||||
ProverResource, PublicValues, zkVM, zkVMProgramDigest,
|
||||
};
|
||||
use sp1_sdk::{SP1ProofMode, SP1ProofWithPublicValues, SP1ProvingKey, SP1Stdin, SP1VerifyingKey};
|
||||
use std::{
|
||||
@@ -23,7 +23,7 @@ include!(concat!(env!("OUT_DIR"), "/name_and_sdk_version.rs"));
|
||||
pub struct EreSP1 {
|
||||
program: SP1Program,
|
||||
/// Prover resource configuration for creating clients
|
||||
resource: ProverResourceType,
|
||||
resource: ProverResource,
|
||||
/// Proving key
|
||||
pk: SP1ProvingKey,
|
||||
/// Verification key
|
||||
@@ -39,7 +39,7 @@ pub struct EreSP1 {
|
||||
}
|
||||
|
||||
impl EreSP1 {
|
||||
pub fn new(program: SP1Program, resource: ProverResourceType) -> Result<Self, Error> {
|
||||
pub fn new(program: SP1Program, resource: ProverResource) -> Result<Self, Error> {
|
||||
let prover = Prover::new(&resource)?;
|
||||
let (pk, vk) = prover.setup(&program.elf)?;
|
||||
Ok(Self {
|
||||
@@ -97,7 +97,7 @@ impl zkVM for EreSP1 {
|
||||
let mut prover = self.prover_mut()?;
|
||||
|
||||
// Restart GPU prover if the prover is dropped before.
|
||||
if matches!(self.resource, ProverResourceType::Gpu) && matches!(&*prover, Prover::Cpu(_)) {
|
||||
if matches!(self.resource, ProverResource::Gpu) && matches!(&*prover, Prover::Cpu(_)) {
|
||||
*prover = Prover::new(&self.resource).and_then(|prover| {
|
||||
prover.setup(&self.program.elf)?;
|
||||
Ok(prover)
|
||||
@@ -107,7 +107,7 @@ impl zkVM for EreSP1 {
|
||||
let start = Instant::now();
|
||||
let proof =
|
||||
panic::catch_unwind(|| prover.prove(&self.pk, &stdin, mode)).map_err(|err| {
|
||||
if matches!(self.resource, ProverResourceType::Gpu) {
|
||||
if matches!(self.resource, ProverResource::Gpu) {
|
||||
// Drop the panicked GPU prover and replace it with CPU one,
|
||||
// next prove call will try to restart it.
|
||||
take(&mut *prover);
|
||||
@@ -201,7 +201,7 @@ mod tests {
|
||||
use ere_zkvm_interface::{
|
||||
Input,
|
||||
compiler::Compiler,
|
||||
zkvm::{NetworkProverConfig, ProofKind, ProverResourceType, zkVM},
|
||||
zkvm::{ProofKind, ProverResource, RemoteProverConfig, zkVM},
|
||||
};
|
||||
use std::sync::OnceLock;
|
||||
|
||||
@@ -219,7 +219,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_execute() {
|
||||
let program = basic_program();
|
||||
let zkvm = EreSP1::new(program, ProverResourceType::Cpu).unwrap();
|
||||
let zkvm = EreSP1::new(program, ProverResource::Cpu).unwrap();
|
||||
|
||||
let test_case = BasicProgram::<BincodeLegacy>::valid_test_case();
|
||||
run_zkvm_execute(&zkvm, &test_case);
|
||||
@@ -228,7 +228,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_execute_invalid_test_case() {
|
||||
let program = basic_program();
|
||||
let zkvm = EreSP1::new(program, ProverResourceType::Cpu).unwrap();
|
||||
let zkvm = EreSP1::new(program, ProverResource::Cpu).unwrap();
|
||||
|
||||
for input in [
|
||||
Input::new(),
|
||||
@@ -241,7 +241,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_prove() {
|
||||
let program = basic_program();
|
||||
let zkvm = EreSP1::new(program, ProverResourceType::Cpu).unwrap();
|
||||
let zkvm = EreSP1::new(program, ProverResource::Cpu).unwrap();
|
||||
|
||||
let test_case = BasicProgram::<BincodeLegacy>::valid_test_case();
|
||||
run_zkvm_prove(&zkvm, &test_case);
|
||||
@@ -250,7 +250,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_prove_invalid_test_case() {
|
||||
let program = basic_program();
|
||||
let zkvm = EreSP1::new(program, ProverResourceType::Cpu).unwrap();
|
||||
let zkvm = EreSP1::new(program, ProverResource::Cpu).unwrap();
|
||||
|
||||
for input in [
|
||||
Input::new(),
|
||||
@@ -269,13 +269,13 @@ mod tests {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a network prover configuration
|
||||
let network_config = NetworkProverConfig {
|
||||
// Create a remote prover configuration
|
||||
let config = RemoteProverConfig {
|
||||
endpoint: std::env::var("NETWORK_RPC_URL").unwrap_or_default(),
|
||||
api_key: std::env::var("NETWORK_PRIVATE_KEY").ok(),
|
||||
};
|
||||
let program = basic_program();
|
||||
let zkvm = EreSP1::new(program, ProverResourceType::Network(network_config)).unwrap();
|
||||
let zkvm = EreSP1::new(program, ProverResource::Network(config)).unwrap();
|
||||
|
||||
let test_case = BasicProgram::<BincodeLegacy>::valid_test_case();
|
||||
run_zkvm_prove(&zkvm, &test_case);
|
||||
|
||||
@@ -19,6 +19,9 @@ pub enum Error {
|
||||
#[error("Deserialize proofs in Input failed: {0:?}")]
|
||||
DeserializeInputProofs(bincode::error::DecodeError),
|
||||
|
||||
#[error("Missing `api_key` in `RemoteProverConfig`")]
|
||||
MissingApiKey,
|
||||
|
||||
// Execute
|
||||
#[error("SP1 execution failed: {0}")]
|
||||
Execute(#[source] anyhow::Error),
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::zkvm::{Error, panic_msg};
|
||||
use ere_zkvm_interface::{
|
||||
CommonError,
|
||||
zkvm::{NetworkProverConfig, ProverResourceType},
|
||||
CommonError, RemoteProverConfig,
|
||||
zkvm::{ProverResource, ProverResourceKind},
|
||||
};
|
||||
use sp1_sdk::{
|
||||
CpuProver, NetworkProver, Prover as _, ProverClient, SP1ProofMode, SP1ProofWithPublicValues,
|
||||
@@ -27,16 +27,24 @@ pub enum Prover {
|
||||
|
||||
impl Default for Prover {
|
||||
fn default() -> Self {
|
||||
Self::new(&ProverResourceType::Cpu).unwrap()
|
||||
Self::new(&ProverResource::Cpu).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl Prover {
|
||||
pub fn new(resource: &ProverResourceType) -> Result<Self, Error> {
|
||||
pub fn new(resource: &ProverResource) -> Result<Self, Error> {
|
||||
Ok(match resource {
|
||||
ProverResourceType::Cpu => Self::Cpu(ProverClient::builder().cpu().build()),
|
||||
ProverResourceType::Gpu => Self::Gpu(CudaProver::new()?),
|
||||
ProverResourceType::Network(config) => Self::Network(build_network_prover(config)),
|
||||
ProverResource::Cpu => Self::Cpu(ProverClient::builder().cpu().build()),
|
||||
ProverResource::Gpu => Self::Gpu(CudaProver::new()?),
|
||||
ProverResource::Network(config) => Self::Network(build_network_prover(config)?),
|
||||
_ => Err(CommonError::unsupported_prover_resource_kind(
|
||||
resource.kind(),
|
||||
[
|
||||
ProverResourceKind::Cpu,
|
||||
ProverResourceKind::Gpu,
|
||||
ProverResourceKind::Network,
|
||||
],
|
||||
))?,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -168,7 +176,7 @@ impl CudaProver {
|
||||
}
|
||||
}
|
||||
|
||||
fn build_network_prover(config: &NetworkProverConfig) -> NetworkProver {
|
||||
fn build_network_prover(config: &RemoteProverConfig) -> Result<NetworkProver, Error> {
|
||||
let mut builder = ProverClient::builder().network();
|
||||
// Check if we have a private key in the config or environment
|
||||
if let Some(api_key) = &config.api_key {
|
||||
@@ -176,9 +184,7 @@ fn build_network_prover(config: &NetworkProverConfig) -> NetworkProver {
|
||||
} else if let Ok(private_key) = env::var("NETWORK_PRIVATE_KEY") {
|
||||
builder = builder.private_key(&private_key);
|
||||
} else {
|
||||
panic!(
|
||||
"Network proving requires a private key. Set NETWORK_PRIVATE_KEY environment variable or provide api_key in NetworkProverConfig"
|
||||
);
|
||||
return Err(Error::MissingApiKey);
|
||||
}
|
||||
// Set the RPC URL if provided
|
||||
if !config.endpoint.is_empty() {
|
||||
@@ -187,5 +193,5 @@ fn build_network_prover(config: &NetworkProverConfig) -> NetworkProver {
|
||||
builder = builder.rpc_url(&rpc_url);
|
||||
}
|
||||
// Otherwise SP1 SDK will use its default RPC URL
|
||||
builder.build()
|
||||
Ok(builder.build())
|
||||
}
|
||||
|
||||
@@ -19,13 +19,14 @@
|
||||
//!
|
||||
//! # `zkVM` implementation
|
||||
//!
|
||||
//! ## Supported `ProverResourceType`
|
||||
//! ## Supported `ProverResource`
|
||||
//!
|
||||
//! | Resource | Supported |
|
||||
//! | --------- | :-------: |
|
||||
//! | `Cpu` | Yes |
|
||||
//! | `Gpu` | No |
|
||||
//! | `Network` | No |
|
||||
//! | `Cluster` | No |
|
||||
//!
|
||||
//! [`install_ziren_sdk.sh`]: https://github.com/eth-act/ere/blob/master/scripts/sdk_installers/install_ziren_sdk.sh
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ use crate::program::ZirenProgram;
|
||||
use anyhow::bail;
|
||||
use ere_zkvm_interface::zkvm::{
|
||||
CommonError, Input, ProgramExecutionReport, ProgramProvingReport, Proof, ProofKind,
|
||||
ProverResourceType, PublicValues, zkVM, zkVMProgramDigest,
|
||||
ProverResource, ProverResourceKind, PublicValues, zkVM, zkVMProgramDigest,
|
||||
};
|
||||
use std::{panic, time::Instant};
|
||||
use tracing::info;
|
||||
@@ -24,12 +24,12 @@ pub struct EreZiren {
|
||||
}
|
||||
|
||||
impl EreZiren {
|
||||
pub fn new(program: ZirenProgram, resource: ProverResourceType) -> Result<Self, Error> {
|
||||
if matches!(
|
||||
resource,
|
||||
ProverResourceType::Gpu | ProverResourceType::Network(_)
|
||||
) {
|
||||
panic!("Network or Gpu proving not yet implemented for ZKM. Use CPU resource type.");
|
||||
pub fn new(program: ZirenProgram, resource: ProverResource) -> Result<Self, Error> {
|
||||
if !matches!(resource, ProverResource::Cpu) {
|
||||
Err(CommonError::unsupported_prover_resource_kind(
|
||||
resource.kind(),
|
||||
[ProverResourceKind::Cpu],
|
||||
))?;
|
||||
}
|
||||
let (pk, vk) = CpuProver::new().setup(program.elf());
|
||||
Ok(Self { program, pk, vk })
|
||||
@@ -160,7 +160,7 @@ mod tests {
|
||||
};
|
||||
use ere_zkvm_interface::{
|
||||
compiler::Compiler,
|
||||
zkvm::{Input, ProofKind, ProverResourceType, zkVM},
|
||||
zkvm::{Input, ProofKind, ProverResource, zkVM},
|
||||
};
|
||||
use std::sync::OnceLock;
|
||||
|
||||
@@ -178,7 +178,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_execute() {
|
||||
let program = basic_program();
|
||||
let zkvm = EreZiren::new(program, ProverResourceType::Cpu).unwrap();
|
||||
let zkvm = EreZiren::new(program, ProverResource::Cpu).unwrap();
|
||||
|
||||
let test_case = BasicProgram::<BincodeLegacy>::valid_test_case();
|
||||
run_zkvm_execute(&zkvm, &test_case);
|
||||
@@ -187,7 +187,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_execute_invalid_test_case() {
|
||||
let program = basic_program();
|
||||
let zkvm = EreZiren::new(program, ProverResourceType::Cpu).unwrap();
|
||||
let zkvm = EreZiren::new(program, ProverResource::Cpu).unwrap();
|
||||
|
||||
for input in [
|
||||
Input::new(),
|
||||
@@ -200,7 +200,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_prove() {
|
||||
let program = basic_program();
|
||||
let zkvm = EreZiren::new(program, ProverResourceType::Cpu).unwrap();
|
||||
let zkvm = EreZiren::new(program, ProverResource::Cpu).unwrap();
|
||||
|
||||
let test_case = BasicProgram::<BincodeLegacy>::valid_test_case();
|
||||
run_zkvm_prove(&zkvm, &test_case);
|
||||
@@ -209,7 +209,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_prove_invalid_test_case() {
|
||||
let program = basic_program();
|
||||
let zkvm = EreZiren::new(program, ProverResourceType::Cpu).unwrap();
|
||||
let zkvm = EreZiren::new(program, ProverResource::Cpu).unwrap();
|
||||
|
||||
for input in [
|
||||
Input::new(),
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
use ere_zkvm_interface::zkvm::ProofKind;
|
||||
use ere_zkvm_interface::zkvm::{CommonError, ProofKind};
|
||||
use thiserror::Error;
|
||||
use zkm_sdk::{ZKMProofKind, ZKMVerificationError};
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum Error {
|
||||
#[error(transparent)]
|
||||
CommonError(#[from] CommonError),
|
||||
|
||||
// Execute
|
||||
#[error("Ziren execution failed: {0}")]
|
||||
Execute(#[source] anyhow::Error),
|
||||
|
||||
@@ -8,18 +8,28 @@ license.workspace = true
|
||||
[dependencies]
|
||||
anyhow.workspace = true
|
||||
blake3.workspace = true
|
||||
bytemuck.workspace = true
|
||||
bytemuck = { workspace = true, features = ["extern_crate_alloc"] }
|
||||
futures-util.workspace = true
|
||||
http.workspace = true
|
||||
parking_lot.workspace = true
|
||||
serde.workspace = true
|
||||
strum = { workspace = true, features = ["derive"] }
|
||||
tempfile.workspace = true
|
||||
thiserror.workspace = true
|
||||
tokio = { workspace = true, features = ["rt-multi-thread"] }
|
||||
tonic.workspace = true
|
||||
tracing.workspace = true
|
||||
uuid = { workspace = true, features = ["v4"] }
|
||||
wait-timeout.workspace = true
|
||||
|
||||
# Local dependencies
|
||||
ere-compile-utils = { workspace = true, optional = true }
|
||||
ere-zkvm-interface.workspace = true
|
||||
|
||||
# Zisk dependencies
|
||||
zisk-distributed-grpc-api.workspace = true
|
||||
zisk-proofman-verifier.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
ere-test-utils = { workspace = true, features = ["host"] }
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ mod tests {
|
||||
io::serde::cbor::Cbor,
|
||||
program::basic::BasicProgram,
|
||||
};
|
||||
use ere_zkvm_interface::{ProverResourceType, compiler::Compiler};
|
||||
use ere_zkvm_interface::{ProverResource, compiler::Compiler};
|
||||
|
||||
#[test]
|
||||
fn test_compile() {
|
||||
@@ -81,7 +81,7 @@ mod tests {
|
||||
fn test_execute() {
|
||||
let guest_directory = testing_guest_directory("zisk", "basic_go");
|
||||
let program = GoCustomized.compile(&guest_directory).unwrap();
|
||||
let zkvm = EreZisk::new(program, ProverResourceType::Cpu).unwrap();
|
||||
let zkvm = EreZisk::new(program, ProverResource::Cpu).unwrap();
|
||||
|
||||
let test_case = BasicProgram::<Cbor>::valid_test_case();
|
||||
run_zkvm_execute(&zkvm, &test_case);
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
//! ## `zkVM` requirements
|
||||
//!
|
||||
//! - Installation via [`ziskup`]
|
||||
//! - `cargo-zisk-cuda` - Used by `zkVM::prove` if `ProverResourceType::Gpu` is
|
||||
//! - `cargo-zisk-cuda` - Used by `zkVM::prove` if `ProverResource::Gpu` is
|
||||
//! selected
|
||||
//!
|
||||
//! # `Compiler` implementation
|
||||
@@ -30,13 +30,31 @@
|
||||
//!
|
||||
//! # `zkVM` implementation
|
||||
//!
|
||||
//! ## Supported `ProverResourceType`
|
||||
//! ## Supported `ProverResource`
|
||||
//!
|
||||
//! | Resource | Supported |
|
||||
//! | --------- | :-------: |
|
||||
//! | `Cpu` | Yes |
|
||||
//! | `Gpu` | Yes |
|
||||
//! | `Network` | No |
|
||||
//! | `Cluster` | Yes |
|
||||
//!
|
||||
//! ## Environment variables
|
||||
//!
|
||||
//! | Variable | Type | Default | Description |
|
||||
//! | -------------------------------------- | ----- | ------- | ---------------------------------------------------------------------- |
|
||||
//! | `ERE_ZISK_SETUP_ON_INIT` | Flag | | Trigger ROM setup at initialization instead of lazily |
|
||||
//! | `ERE_ZISK_PORT` | Value | | Pass `--port {port}` to the server |
|
||||
//! | `ERE_ZISK_UNLOCK_MAPPED_MEMORY` | Flag | | Pass `--unlock-mapped-memory` to the server |
|
||||
//! | `ERE_ZISK_MINIMAL_MEMORY` | Flag | | Pass `--minimal_memory` to the server |
|
||||
//! | `ERE_ZISK_PREALLOCATE` | Flag | | Pass `--preallocate` to the server |
|
||||
//! | `ERE_ZISK_SHARED_TABLES` | Flag | | Pass `--shared-tables` to the server |
|
||||
//! | `ERE_ZISK_MAX_STREAMS` | Value | | Pass `--max-streams {max_streams}` to the server |
|
||||
//! | `ERE_ZISK_NUMBER_THREADS_WITNESS` | Value | | Pass `--number-threads-witness {number_threads_witness}` to the server |
|
||||
//! | `ERE_ZISK_MAX_WITNESS_STORED` | Value | | Pass `--max-witness-stored {max_witness_stored}` to the server |
|
||||
//! | `ERE_ZISK_START_SERVER_TIMEOUT_SEC` | Value | `120` | Timeout waiting for server to start |
|
||||
//! | `ERE_ZISK_SHUTDOWN_SERVER_TIMEOUT_SEC` | Value | `30` | Timeout for server shutdown |
|
||||
//! | `ERE_ZISK_PROVE_TIMEOUT_SEC` | Value | `3600` | Timeout for proof generation |
|
||||
//!
|
||||
//! [`install_zisk_sdk.sh`]: https://github.com/eth-act/ere/blob/master/scripts/sdk_installers/install_zisk_sdk.sh
|
||||
//! [`install_tamago.sh`]: https://github.com/eth-act/ere/blob/master/scripts/install_tamago.sh
|
||||
|
||||
@@ -1,20 +1,18 @@
|
||||
use crate::{
|
||||
program::ZiskProgram,
|
||||
zkvm::sdk::{RomDigest, START_SERVER_TIMEOUT, ZiskOptions, ZiskSdk, ZiskServer},
|
||||
zkvm::sdk::{RomDigest, ZiskSdk},
|
||||
};
|
||||
use anyhow::bail;
|
||||
use ere_zkvm_interface::zkvm::{
|
||||
CommonError, Input, ProgramExecutionReport, ProgramProvingReport, Proof, ProofKind,
|
||||
ProverResourceType, PublicValues, zkVM, zkVMProgramDigest,
|
||||
ProverResource, PublicValues, zkVM, zkVMProgramDigest,
|
||||
};
|
||||
use std::{
|
||||
sync::{Mutex, MutexGuard},
|
||||
time::Instant,
|
||||
};
|
||||
use tracing::error;
|
||||
use std::time::Instant;
|
||||
|
||||
mod cluster_client;
|
||||
mod error;
|
||||
mod sdk;
|
||||
mod server;
|
||||
|
||||
pub use error::Error;
|
||||
|
||||
@@ -22,57 +20,21 @@ include!(concat!(env!("OUT_DIR"), "/name_and_sdk_version.rs"));
|
||||
|
||||
pub struct EreZisk {
|
||||
sdk: ZiskSdk,
|
||||
/// Use `Mutex` because the server can only handle signle proving task at a
|
||||
/// time.
|
||||
///
|
||||
/// Use `Option` inside to lazily initialize only when `prove` is called.
|
||||
server: Mutex<Option<ZiskServer>>,
|
||||
}
|
||||
|
||||
impl EreZisk {
|
||||
pub fn new(program: ZiskProgram, resource: ProverResourceType) -> Result<Self, Error> {
|
||||
if matches!(resource, ProverResourceType::Network(_)) {
|
||||
panic!("Network proving not yet implemented for ZisK. Use CPU or GPU resource type.");
|
||||
}
|
||||
let sdk = ZiskSdk::new(program.elf, resource, ZiskOptions::from_env())?;
|
||||
Ok(Self {
|
||||
sdk,
|
||||
server: Mutex::new(None),
|
||||
})
|
||||
}
|
||||
|
||||
fn server(&'_ self) -> Result<MutexGuard<'_, Option<ZiskServer>>, Error> {
|
||||
let mut server = self.server.lock().map_err(|_| Error::MutexPoisoned)?;
|
||||
|
||||
if server
|
||||
.as_ref()
|
||||
.is_none_or(|server| server.status(START_SERVER_TIMEOUT).is_err())
|
||||
{
|
||||
const MAX_RETRY: usize = 3;
|
||||
let mut retry = 0;
|
||||
*server = loop {
|
||||
drop(server.take());
|
||||
match self.sdk.server() {
|
||||
Ok(server) => break Some(server),
|
||||
Err(Error::TimeoutWaitingServerReady) if retry < MAX_RETRY => {
|
||||
error!("Timeout waiting server ready, restarting...");
|
||||
retry += 1;
|
||||
continue;
|
||||
}
|
||||
Err(err) => return Err(err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Use `MutexGuard::map` to unwrap the inner `Option` when it's stabilized.
|
||||
Ok(server)
|
||||
pub fn new(program: ZiskProgram, resource: ProverResource) -> Result<Self, Error> {
|
||||
let sdk = ZiskSdk::new(program.elf, resource)?;
|
||||
Ok(Self { sdk })
|
||||
}
|
||||
}
|
||||
|
||||
impl zkVM for EreZisk {
|
||||
fn execute(&self, input: &Input) -> anyhow::Result<(PublicValues, ProgramExecutionReport)> {
|
||||
if input.proofs.is_some() {
|
||||
bail!(CommonError::unsupported_input("no dedicated proofs stream"))
|
||||
bail!(Error::from(CommonError::unsupported_input(
|
||||
"no dedicated proofs stream"
|
||||
)))
|
||||
}
|
||||
|
||||
let start = Instant::now();
|
||||
@@ -95,21 +57,18 @@ impl zkVM for EreZisk {
|
||||
proof_kind: ProofKind,
|
||||
) -> anyhow::Result<(PublicValues, Proof, ProgramProvingReport)> {
|
||||
if input.proofs.is_some() {
|
||||
bail!(CommonError::unsupported_input("no dedicated proofs stream"))
|
||||
bail!(Error::from(CommonError::unsupported_input(
|
||||
"no dedicated proofs stream"
|
||||
)))
|
||||
}
|
||||
if proof_kind != ProofKind::Compressed {
|
||||
bail!(CommonError::unsupported_proof_kind(
|
||||
bail!(Error::from(CommonError::unsupported_proof_kind(
|
||||
proof_kind,
|
||||
[ProofKind::Compressed]
|
||||
))
|
||||
)))
|
||||
}
|
||||
|
||||
let mut server = self.server()?;
|
||||
let server = server.as_mut().expect("server initialized");
|
||||
|
||||
let start = Instant::now();
|
||||
let (public_values, proof) = server.prove(input.stdin())?;
|
||||
let proving_time = start.elapsed();
|
||||
let (public_values, proof, proving_time) = self.sdk.prove(input.stdin())?;
|
||||
|
||||
Ok((
|
||||
public_values,
|
||||
@@ -120,10 +79,10 @@ impl zkVM for EreZisk {
|
||||
|
||||
fn verify(&self, proof: &Proof) -> anyhow::Result<PublicValues> {
|
||||
let Proof::Compressed(proof) = proof else {
|
||||
bail!(CommonError::unsupported_proof_kind(
|
||||
bail!(Error::from(CommonError::unsupported_proof_kind(
|
||||
proof.kind(),
|
||||
[ProofKind::Compressed]
|
||||
))
|
||||
)))
|
||||
};
|
||||
|
||||
Ok(self.sdk.verify(proof)?)
|
||||
@@ -155,8 +114,9 @@ mod tests {
|
||||
program::basic::BasicProgram,
|
||||
};
|
||||
use ere_zkvm_interface::{
|
||||
RemoteProverConfig,
|
||||
compiler::Compiler,
|
||||
zkvm::{Input, ProofKind, ProverResourceType, zkVM},
|
||||
zkvm::{Input, ProofKind, ProverResource, zkVM},
|
||||
};
|
||||
use std::sync::{Mutex, OnceLock};
|
||||
|
||||
@@ -178,7 +138,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_execute() {
|
||||
let program = basic_program();
|
||||
let zkvm = EreZisk::new(program, ProverResourceType::Cpu).unwrap();
|
||||
let zkvm = EreZisk::new(program, ProverResource::Cpu).unwrap();
|
||||
|
||||
let test_case = BasicProgram::<BincodeLegacy>::valid_test_case();
|
||||
run_zkvm_execute(&zkvm, &test_case);
|
||||
@@ -187,7 +147,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_execute_invalid_test_case() {
|
||||
let program = basic_program();
|
||||
let zkvm = EreZisk::new(program, ProverResourceType::Cpu).unwrap();
|
||||
let zkvm = EreZisk::new(program, ProverResource::Cpu).unwrap();
|
||||
|
||||
for input in [
|
||||
Input::new(),
|
||||
@@ -200,7 +160,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_prove() {
|
||||
let program = basic_program();
|
||||
let zkvm = EreZisk::new(program, ProverResourceType::Cpu).unwrap();
|
||||
let zkvm = EreZisk::new(program, ProverResource::Cpu).unwrap();
|
||||
|
||||
let _guard = PROVE_LOCK.lock().unwrap();
|
||||
|
||||
@@ -211,7 +171,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_prove_invalid_test_case() {
|
||||
let program = basic_program();
|
||||
let zkvm = EreZisk::new(program, ProverResourceType::Cpu).unwrap();
|
||||
let zkvm = EreZisk::new(program, ProverResource::Cpu).unwrap();
|
||||
|
||||
let _guard = PROVE_LOCK.lock().unwrap();
|
||||
|
||||
@@ -222,4 +182,23 @@ mod tests {
|
||||
zkvm.prove(&input, ProofKind::default()).unwrap_err();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "Requires ZisK cluster running"]
|
||||
fn test_cluster_prove() {
|
||||
let program = basic_program();
|
||||
let zkvm = EreZisk::new(
|
||||
program,
|
||||
ProverResource::Cluster(RemoteProverConfig {
|
||||
endpoint: "http://127.0.0.1:50051".to_string(),
|
||||
..Default::default()
|
||||
}),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let _guard = PROVE_LOCK.lock().unwrap();
|
||||
|
||||
let test_case = BasicProgram::<BincodeLegacy>::valid_test_case();
|
||||
run_zkvm_prove(&zkvm, &test_case);
|
||||
}
|
||||
}
|
||||
|
||||
183
crates/zkvm/zisk/src/zkvm/cluster_client.rs
Normal file
183
crates/zkvm/zisk/src/zkvm/cluster_client.rs
Normal file
@@ -0,0 +1,183 @@
|
||||
//! Remote ZisK cluster proving.
|
||||
|
||||
use crate::zkvm::Error;
|
||||
use ere_zkvm_interface::zkvm::RemoteProverConfig;
|
||||
use futures_util::StreamExt;
|
||||
use std::sync::OnceLock;
|
||||
use std::time::Duration;
|
||||
use tonic::transport::Channel;
|
||||
use tracing::debug;
|
||||
use zisk_distributed_grpc_api::{
|
||||
ErrorResponse, InputMode, LaunchProofRequest, ProofStatusType, SubscribeToProofRequest,
|
||||
SystemStatusRequest, launch_proof_response, system_status_response,
|
||||
zisk_distributed_api_client::ZiskDistributedApiClient,
|
||||
};
|
||||
|
||||
/// Wrapper for the ZisK cluster client.
|
||||
///
|
||||
/// Connects to the ZisK cluster via gRPC and submits proof jobs.
|
||||
pub struct ClusterClient {
|
||||
client: ZiskDistributedApiClient<Channel>,
|
||||
}
|
||||
|
||||
impl ClusterClient {
|
||||
/// Create a new ClusterClient that connects to the cluster.
|
||||
pub fn new(config: &RemoteProverConfig) -> Result<Self, Error> {
|
||||
let client = block_on(connect(&config.endpoint))?;
|
||||
Ok(Self { client })
|
||||
}
|
||||
|
||||
/// Sync wrapper for [`Self::prove_async`].
|
||||
pub fn prove(&self, input: &[u8]) -> Result<(Vec<u8>, Duration), Error> {
|
||||
block_on(self.prove_async(input))
|
||||
}
|
||||
|
||||
/// Send proof request to cluster and wait for completion.
|
||||
///
|
||||
/// Returns the proof and proving time reported by the cluster.
|
||||
async fn prove_async(&self, input: &[u8]) -> Result<(Vec<u8>, Duration), Error> {
|
||||
let mut client = self.client.clone();
|
||||
|
||||
// Check system status to get available compute capacity
|
||||
|
||||
debug!("Checking system status...");
|
||||
|
||||
let status_response = client.system_status(SystemStatusRequest {}).await?;
|
||||
|
||||
let compute_capacity = match status_response.into_inner().result {
|
||||
Some(system_status_response::Result::Status(status)) => {
|
||||
debug!(
|
||||
total_workers = status.total_workers,
|
||||
compute_capacity = status.compute_capacity,
|
||||
idle_workers = status.idle_workers,
|
||||
busy_workers = status.busy_workers,
|
||||
active_jobs = status.active_jobs,
|
||||
"System status",
|
||||
);
|
||||
|
||||
if status.total_workers == 0 || status.compute_capacity == 0 {
|
||||
return Err(cluster_error("No worker available in the cluster"));
|
||||
}
|
||||
if status.active_jobs != 0 {
|
||||
return Err(cluster_error("Cluster is busy with another proof job"));
|
||||
}
|
||||
|
||||
status.compute_capacity
|
||||
}
|
||||
Some(system_status_response::Result::Error(res)) => {
|
||||
return Err(cluster_error_from_response("System status error", res));
|
||||
}
|
||||
None => {
|
||||
return Err(cluster_error("Received empty system status response"));
|
||||
}
|
||||
};
|
||||
|
||||
// Launch proof
|
||||
|
||||
let data_id = uuid::Uuid::new_v4().to_string();
|
||||
|
||||
debug!(data_id = data_id, "Launching proof...");
|
||||
|
||||
let launch_request = LaunchProofRequest {
|
||||
data_id,
|
||||
compute_capacity,
|
||||
input_mode: InputMode::Data.into(),
|
||||
input_path: None,
|
||||
input_data: Some(input.to_vec()),
|
||||
simulated_node: None,
|
||||
};
|
||||
|
||||
let launch_response = client.launch_proof(launch_request).await?;
|
||||
|
||||
let job_id = match launch_response.into_inner().result {
|
||||
Some(launch_proof_response::Result::JobId(job_id)) => {
|
||||
debug!(job_id = job_id, "Proof launched successfully");
|
||||
|
||||
job_id
|
||||
}
|
||||
Some(launch_proof_response::Result::Error(res)) => {
|
||||
return Err(cluster_error_from_response("Launch proof error", res));
|
||||
}
|
||||
None => {
|
||||
return Err(cluster_error("Received empty launch proof response"));
|
||||
}
|
||||
};
|
||||
|
||||
// Subscribe to proof status updates
|
||||
|
||||
debug!(job_id = job_id, "Subscribing to proof status updates...");
|
||||
|
||||
let stream = client
|
||||
.subscribe_to_proof(SubscribeToProofRequest { job_id })
|
||||
.await?;
|
||||
|
||||
// Wait for proof status update (completion or failure)
|
||||
|
||||
debug!("Waiting for proof status update (completion or failure)...");
|
||||
|
||||
if let Some(update) = stream.into_inner().next().await {
|
||||
let update = update.map_err(cluster_error)?;
|
||||
|
||||
match ProofStatusType::try_from(update.status) {
|
||||
Ok(ProofStatusType::ProofStatusCompleted) => match update.final_proof {
|
||||
Some(final_proof) => {
|
||||
let proof = bytemuck::cast_slice(&final_proof.values).to_vec();
|
||||
let proving_time = Duration::from_millis(update.duration_ms);
|
||||
|
||||
debug!(
|
||||
proof_size = proof.len(),
|
||||
proving_time = ?proving_time,
|
||||
"Proof generated successfully"
|
||||
);
|
||||
|
||||
Ok((proof, proving_time))
|
||||
}
|
||||
None => Err(cluster_error("Missing final proof")),
|
||||
},
|
||||
Ok(ProofStatusType::ProofStatusFailed) => Err(update
|
||||
.error
|
||||
.map(|res| cluster_error_from_response("Proof generation error", res))
|
||||
.unwrap_or_else(|| cluster_error("Unknown error"))),
|
||||
Err(err) => Err(cluster_error(err)),
|
||||
}
|
||||
} else {
|
||||
Err(cluster_error("Stream ended without completion status"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Connect to the ZisK cluster at the given gRPC endpoint.
|
||||
async fn connect(endpoint: &str) -> Result<ZiskDistributedApiClient<Channel>, Error> {
|
||||
let channel = Channel::from_shared(endpoint.to_string())?
|
||||
.connect()
|
||||
.await?;
|
||||
Ok(ZiskDistributedApiClient::new(channel))
|
||||
}
|
||||
|
||||
/// Run a future to completion, reusing the current tokio runtime or creating one.
|
||||
fn block_on<T>(future: impl Future<Output = T>) -> T {
|
||||
match tokio::runtime::Handle::try_current() {
|
||||
Ok(handle) => tokio::task::block_in_place(|| handle.block_on(future)),
|
||||
Err(_) => {
|
||||
static FALLBACK_RT: OnceLock<tokio::runtime::Runtime> = OnceLock::new();
|
||||
FALLBACK_RT
|
||||
.get_or_init(|| tokio::runtime::Runtime::new().expect("Failed to create runtime"))
|
||||
.block_on(future)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `Error::ClusterError`.
|
||||
fn cluster_error(s: impl ToString) -> Error {
|
||||
Error::ClusterError(s.to_string())
|
||||
}
|
||||
|
||||
/// Returns `Error::ClusterError` formatted with error code and message.
|
||||
fn cluster_error_from_response(s: impl ToString, res: ErrorResponse) -> Error {
|
||||
Error::ClusterError(format!(
|
||||
"{}, code: {}, message: {}",
|
||||
s.to_string(),
|
||||
res.code,
|
||||
res.message
|
||||
))
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
use crate::zkvm::sdk::RomDigest;
|
||||
use bytemuck::PodCastError;
|
||||
use ere_zkvm_interface::zkvm::CommonError;
|
||||
use thiserror::Error;
|
||||
|
||||
@@ -20,9 +19,6 @@ pub enum Error {
|
||||
RomSetupFailedBefore,
|
||||
|
||||
// Prove
|
||||
#[error("Mutex of ZiskServer is poisoned")]
|
||||
MutexPoisoned,
|
||||
|
||||
#[error("Server crashed")]
|
||||
ServerCrashed,
|
||||
|
||||
@@ -32,15 +28,28 @@ pub enum Error {
|
||||
#[error("Timeout waiting for server ready")]
|
||||
TimeoutWaitingServerReady,
|
||||
|
||||
#[error("Uknown server status, stdout: {stdout}")]
|
||||
#[error("Unknown server status, stdout: {stdout}")]
|
||||
UnknownServerStatus { stdout: String },
|
||||
|
||||
// Verify
|
||||
#[error("Invalid proof: {0}")]
|
||||
InvalidProof(String),
|
||||
// Cluster
|
||||
#[error("Invalid cluster endpoint: {0}")]
|
||||
InvalidClusterEndpoint(#[from] http::uri::InvalidUri),
|
||||
|
||||
#[error("Cast proof to `u64` slice failed: {0}")]
|
||||
CastProofBytesToU64s(PodCastError),
|
||||
#[error("Cluster gRPC error: {0}")]
|
||||
ClusterGrpcError(#[from] tonic::Status),
|
||||
|
||||
#[error("Failed to connect to cluster: {0}")]
|
||||
ClusterConnectionFailed(#[from] tonic::transport::Error),
|
||||
|
||||
#[error("Cluster error: {0}")]
|
||||
ClusterError(String),
|
||||
|
||||
// Verify
|
||||
#[error("Invalid proof")]
|
||||
InvalidProof,
|
||||
|
||||
#[error("Invalid proof size {0}, expected a multiple of 8")]
|
||||
InvalidProofSize(usize),
|
||||
|
||||
#[error("Invalid public value format")]
|
||||
InvalidPublicValue,
|
||||
|
||||
@@ -1,162 +1,59 @@
|
||||
use crate::zkvm::Error;
|
||||
use ere_zkvm_interface::zkvm::{CommonError, ProverResourceType, PublicValues};
|
||||
use crate::zkvm::cluster_client::ClusterClient;
|
||||
use crate::zkvm::server::{ZiskServer, ZiskServerOptions};
|
||||
use ere_zkvm_interface::zkvm::{CommonError, ProverResource, ProverResourceKind, PublicValues};
|
||||
use std::borrow::Cow;
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
use std::{
|
||||
collections::BTreeMap,
|
||||
env, fs,
|
||||
io::{BufRead, Write},
|
||||
iter,
|
||||
net::{Ipv4Addr, TcpStream},
|
||||
path::{Path, PathBuf},
|
||||
process::{Child, Command, Stdio},
|
||||
io::BufRead,
|
||||
mem::transmute,
|
||||
path::PathBuf,
|
||||
sync::OnceLock,
|
||||
thread,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
use strum::{EnumIter, IntoEnumIterator};
|
||||
use tempfile::tempdir;
|
||||
use tracing::{error, info};
|
||||
use wait_timeout::ChildExt;
|
||||
use tracing::info;
|
||||
|
||||
pub const START_SERVER_TIMEOUT: Duration = Duration::from_secs(120); // 2 mins
|
||||
pub const SHUTDOWN_SERVER_TIMEOUT: Duration = Duration::from_secs(30); // 30 secs
|
||||
pub const DEFAULT_PROVE_TIMEOUT: Duration = Duration::from_secs(3600); // 1 hour
|
||||
/// Verifying key of the aggregation proof.
|
||||
///
|
||||
/// Extracted from `$HOME/.zisk/provingKey/zisk/vadcop_final/vadcop_final.verkey.json`.
|
||||
pub const VADCOP_FINAL_VK: [u8; 32] = unsafe {
|
||||
// Use `transmute` to keep the endianness because `zisk_proofman_verifier::verify` will
|
||||
// use `bytemuck` to cast it to `[u64; 4]`.
|
||||
transmute([
|
||||
723851053263266420u64,
|
||||
2272245643171245153u64,
|
||||
9868173762158752255u64,
|
||||
6004219199197288727u64,
|
||||
])
|
||||
};
|
||||
|
||||
/// Merkle root of ROM trace generated by `cargo-zisk rom-setup`.
|
||||
pub type RomDigest = [u64; 4];
|
||||
|
||||
/// Options of `cargo-zisk` commands.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, EnumIter)]
|
||||
pub enum ZiskOption {
|
||||
Port,
|
||||
UnlockMappedMemory, // Should be set if locked memory is not enough
|
||||
MinimalMemory,
|
||||
// GPU options
|
||||
Preallocate, // Should be set only if GPU memory is enough
|
||||
SharedTables,
|
||||
MaxStreams,
|
||||
NumberThreadsWitness,
|
||||
MaxWitnessStored,
|
||||
}
|
||||
|
||||
impl ZiskOption {
|
||||
/// The key of the env variable to read from.
|
||||
fn env_var_key(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Port => "ZISK_PORT",
|
||||
Self::UnlockMappedMemory => "ZISK_UNLOCK_MAPPED_MEMORY",
|
||||
Self::MinimalMemory => "ZISK_MINIMAL_MEMORY",
|
||||
Self::Preallocate => "ZISK_PREALLOCATE",
|
||||
Self::SharedTables => "ZISK_SHARED_TABLES",
|
||||
Self::MaxStreams => "ZISK_MAX_STREAMS",
|
||||
Self::NumberThreadsWitness => "ZISK_NUMBER_THREADS_WITNESS",
|
||||
Self::MaxWitnessStored => "ZISK_MAX_WITNESS_STORED",
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether the option is a flag (false-by-default boolean option) or not.
|
||||
///
|
||||
/// When we read the option from env variable, if the option is a flag,
|
||||
/// we only check if the env variable is set or not.
|
||||
fn is_flag(&self) -> bool {
|
||||
match self {
|
||||
Self::UnlockMappedMemory
|
||||
| Self::MinimalMemory
|
||||
| Self::Preallocate
|
||||
| Self::SharedTables => true,
|
||||
Self::Port | Self::MaxStreams | Self::NumberThreadsWitness | Self::MaxWitnessStored => {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The option key to be appended to `cargo-zisk` command arguments.
|
||||
fn key(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Port => "--port",
|
||||
Self::UnlockMappedMemory => "--unlock-mapped-memory",
|
||||
// NOTE: Use snake case for `prove-client` command
|
||||
// Issue for tracking: https://github.com/eth-act/ere/issues/151.
|
||||
Self::MinimalMemory => "--minimal_memory",
|
||||
Self::Preallocate => "--preallocate",
|
||||
Self::SharedTables => "--shared-tables",
|
||||
Self::MaxStreams => "--max-streams",
|
||||
Self::NumberThreadsWitness => "--number-threads-witness",
|
||||
Self::MaxWitnessStored => "--max-witness-stored",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ZiskOptions(BTreeMap<ZiskOption, String>);
|
||||
|
||||
impl ZiskOptions {
|
||||
/// Read options from env variables.
|
||||
pub fn from_env() -> Self {
|
||||
Self(
|
||||
ZiskOption::iter()
|
||||
.flat_map(|option| env::var(option.env_var_key()).ok().map(|val| (option, val)))
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns `cargo-zisk` command arguments by given options that have been
|
||||
/// set.
|
||||
fn args(&self, options: impl IntoIterator<Item = ZiskOption>) -> impl Iterator<Item = &str> {
|
||||
options
|
||||
.into_iter()
|
||||
.filter(|option| self.0.contains_key(option))
|
||||
.flat_map(|option| {
|
||||
iter::once(option.key())
|
||||
.chain((!option.is_flag()).then(|| self.0[&option].as_str()))
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns `cargo-zisk server` command arguments.
|
||||
fn server_args(&self) -> impl Iterator<Item = &str> {
|
||||
self.args([
|
||||
ZiskOption::Port,
|
||||
ZiskOption::UnlockMappedMemory,
|
||||
ZiskOption::Preallocate,
|
||||
ZiskOption::SharedTables,
|
||||
ZiskOption::MaxStreams,
|
||||
ZiskOption::NumberThreadsWitness,
|
||||
ZiskOption::MaxWitnessStored,
|
||||
])
|
||||
}
|
||||
|
||||
/// Returns `cargo-zisk prove-client` command arguments.
|
||||
fn prove_client_args(&self) -> impl Iterator<Item = &str> {
|
||||
self.args([ZiskOption::Port])
|
||||
}
|
||||
|
||||
/// Returns `cargo-zisk prove-client prove` command arguments.
|
||||
fn prove_args(&self) -> impl Iterator<Item = &str> {
|
||||
self.prove_client_args()
|
||||
.chain(self.args([ZiskOption::MinimalMemory]))
|
||||
}
|
||||
pub enum ZiskProver {
|
||||
Server(ZiskServer),
|
||||
Cluster(ClusterClient),
|
||||
}
|
||||
|
||||
pub struct ZiskSdk {
|
||||
elf_path: PathBuf,
|
||||
cuda: bool,
|
||||
options: ZiskOptions,
|
||||
/// ROM digest will be setup only when `ZiskSdk::server` is called.
|
||||
resource: ProverResource,
|
||||
/// ROM digest will be setup when `ZiskSdk::prove` or `ZiskSdk::verify`
|
||||
/// is called, or if env variable `ERE_ZISK_SETUP_ON_INIT` is set.
|
||||
///
|
||||
/// Use `Option` inside because ROM setup might fail, we can get rid of
|
||||
/// it if `OnceLock::get_or_try_init` is stabilized.
|
||||
rom_digest: OnceLock<Option<RomDigest>>,
|
||||
/// Prover instance, either a local server or a cluster client.
|
||||
prover: ZiskProver,
|
||||
}
|
||||
|
||||
impl ZiskSdk {
|
||||
/// Returns SDK for the ELF.
|
||||
pub fn new(
|
||||
elf: Vec<u8>,
|
||||
resource: ProverResourceType,
|
||||
options: ZiskOptions,
|
||||
) -> Result<Self, Error> {
|
||||
if matches!(resource, ProverResourceType::Network(_)) {
|
||||
panic!("Network proving not yet implemented for ZisK. Use CPU or GPU resource type.");
|
||||
}
|
||||
pub fn new(elf: Vec<u8>, resource: ProverResource) -> Result<Self, Error> {
|
||||
// Save ELF to `~/.zisk/cache` along with the ROM binaries, to avoid it
|
||||
// been cleaned up during a long run process.
|
||||
let cache_dir_path = dot_zisk_dir_path().join("cache");
|
||||
@@ -170,12 +67,39 @@ impl ZiskSdk {
|
||||
|
||||
fs::write(&elf_path, elf).map_err(|err| CommonError::write_file("elf", &elf_path, err))?;
|
||||
|
||||
Ok(Self {
|
||||
let prover = match &resource {
|
||||
ProverResource::Cpu | ProverResource::Gpu => ZiskProver::Server(ZiskServer::new(
|
||||
&elf_path,
|
||||
resource.is_gpu(),
|
||||
ZiskServerOptions::from_env(),
|
||||
)),
|
||||
ProverResource::Cluster(config) => ZiskProver::Cluster(ClusterClient::new(config)?),
|
||||
_ => Err(CommonError::unsupported_prover_resource_kind(
|
||||
resource.kind(),
|
||||
[
|
||||
ProverResourceKind::Cpu,
|
||||
ProverResourceKind::Gpu,
|
||||
ProverResourceKind::Cluster,
|
||||
],
|
||||
))?,
|
||||
};
|
||||
|
||||
let sdk = Self {
|
||||
elf_path,
|
||||
cuda: matches!(resource, ProverResourceType::Gpu),
|
||||
options,
|
||||
resource,
|
||||
rom_digest: OnceLock::new(),
|
||||
})
|
||||
prover,
|
||||
};
|
||||
|
||||
if env::var_os("ERE_ZISK_SETUP_ON_INIT").is_some() {
|
||||
sdk.rom_digest()?;
|
||||
|
||||
if let ZiskProver::Server(server) = &sdk.prover {
|
||||
server.ensure_ready()?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(sdk)
|
||||
}
|
||||
|
||||
/// Execute the ELF with the given `input`.
|
||||
@@ -233,7 +157,7 @@ impl ZiskSdk {
|
||||
// FIXME: Use `get_or_try_init` when it is stabilized
|
||||
let mut result = Ok(());
|
||||
let rom_digest = *self.rom_digest.get_or_init(|| {
|
||||
check_setup(self.cuda)
|
||||
check_setup(self.resource.is_gpu())
|
||||
.and_then(|_| rom_setup(&self.elf_path))
|
||||
.map_err(|err| result = Err(err))
|
||||
.ok()
|
||||
@@ -242,75 +166,51 @@ impl ZiskSdk {
|
||||
rom_digest.ok_or(Error::RomSetupFailedBefore)
|
||||
}
|
||||
|
||||
/// Start a server of the ELF.
|
||||
pub fn server(&self) -> Result<ZiskServer, Error> {
|
||||
// Setup ROM and get ROM digest if it's not done yet.
|
||||
let rom_digest = self.rom_digest()?;
|
||||
/// Prove the ELF with the given input.
|
||||
///
|
||||
/// Returns the public values, proof, and proving time.
|
||||
pub fn prove(&self, input: &[u8]) -> Result<(PublicValues, Vec<u8>, Duration), Error> {
|
||||
let (proof, proving_time) = match &self.prover {
|
||||
ZiskProver::Cluster(client) => client.prove(input)?,
|
||||
ZiskProver::Server(server) => {
|
||||
self.rom_digest()?;
|
||||
|
||||
let (cargo_zisk, witness_lib_path) = if self.cuda {
|
||||
let witness_lib_path = dot_zisk_dir_path()
|
||||
.join("bin")
|
||||
.join("libzisk_witness_cuda.so");
|
||||
("cargo-zisk-cuda", Some(witness_lib_path))
|
||||
} else {
|
||||
("cargo-zisk", None)
|
||||
let start = Instant::now();
|
||||
let proof = server.prove(input)?;
|
||||
let proving_time = start.elapsed();
|
||||
|
||||
(proof, proving_time)
|
||||
}
|
||||
};
|
||||
|
||||
info!("Starting ZisK server...");
|
||||
|
||||
let mut cmd = Command::new(cargo_zisk);
|
||||
cmd.arg("server")
|
||||
.args(self.options.server_args())
|
||||
.arg("--elf")
|
||||
.arg(&self.elf_path)
|
||||
.arg("--aggregation");
|
||||
if let Some(witness_lib_path) = witness_lib_path {
|
||||
cmd.arg("--witness-lib").arg(witness_lib_path);
|
||||
}
|
||||
|
||||
let child = cmd.spawn().map_err(|err| CommonError::command(&cmd, err))?;
|
||||
let server = ZiskServer {
|
||||
options: self.options.clone(),
|
||||
rom_digest,
|
||||
child,
|
||||
};
|
||||
|
||||
server.wait_until_ready()?;
|
||||
|
||||
Ok(server)
|
||||
}
|
||||
|
||||
/// Verify the proof of the ELF, and returns public values.
|
||||
pub fn verify(&self, proof: &[u8]) -> Result<PublicValues, Error> {
|
||||
let rom_digest = self.rom_digest()?;
|
||||
|
||||
let tempdir = tempdir().map_err(CommonError::tempdir)?;
|
||||
let proof_path = tempdir.path().join("proof");
|
||||
|
||||
fs::write(&proof_path, proof)
|
||||
.map_err(|err| CommonError::write_file("proof", &proof_path, err))?;
|
||||
|
||||
let mut cmd = Command::new("cargo-zisk");
|
||||
let output = cmd
|
||||
.arg("verify")
|
||||
.arg("--proof")
|
||||
.arg(&proof_path)
|
||||
.output()
|
||||
.map_err(|err| CommonError::command(&cmd, err))?;
|
||||
|
||||
if !output.status.success() {
|
||||
Err(Error::InvalidProof(
|
||||
String::from_utf8_lossy(&output.stderr).to_string(),
|
||||
))?
|
||||
}
|
||||
|
||||
let proof = fs::read(&proof_path)
|
||||
.map_err(|err| CommonError::read_file("proof", &proof_path, err))?;
|
||||
|
||||
// Deserialize public values.
|
||||
let (proved_rom_digest, public_values) = deserialize_public_values(&proof)?;
|
||||
|
||||
// The proved ROM digest should be equal to preprocessed one.
|
||||
let rom_digest = self.rom_digest()?;
|
||||
if proved_rom_digest != rom_digest {
|
||||
return Err(Error::UnexpectedRomDigest {
|
||||
preprocessed: rom_digest,
|
||||
proved: proved_rom_digest,
|
||||
});
|
||||
}
|
||||
|
||||
Ok((public_values, proof, proving_time))
|
||||
}
|
||||
|
||||
/// Verify the proof of the ELF, and returns public values.
|
||||
pub fn verify(&self, proof: &[u8]) -> Result<PublicValues, Error> {
|
||||
let proof = align_to_u64(proof)?;
|
||||
|
||||
if !zisk_proofman_verifier::verify(&proof, &VADCOP_FINAL_VK) {
|
||||
Err(Error::InvalidProof)?
|
||||
}
|
||||
|
||||
// Deserialize public values.
|
||||
let (proved_rom_digest, public_values) = deserialize_public_values(&proof)?;
|
||||
|
||||
// The proved ROM digest should be equal to preprocessed one.
|
||||
let rom_digest = self.rom_digest()?;
|
||||
if proved_rom_digest != rom_digest {
|
||||
return Err(Error::UnexpectedRomDigest {
|
||||
preprocessed: rom_digest,
|
||||
@@ -322,202 +222,6 @@ impl ZiskSdk {
|
||||
}
|
||||
}
|
||||
|
||||
/// ZisK server status returned from `cargo-zisk prove-client status`.
|
||||
#[derive(Debug)]
|
||||
pub enum ZiskServerStatus {
|
||||
Idle,
|
||||
Working,
|
||||
}
|
||||
|
||||
/// Wrapper for ZisK server child process.
|
||||
pub struct ZiskServer {
|
||||
options: ZiskOptions,
|
||||
rom_digest: RomDigest,
|
||||
child: Child,
|
||||
}
|
||||
|
||||
impl Drop for ZiskServer {
|
||||
fn drop(&mut self) {
|
||||
info!("Shutting down ZisK server");
|
||||
|
||||
let mut cmd = Command::new("cargo-zisk");
|
||||
let result = cmd
|
||||
.args(["prove-client", "shutdown"])
|
||||
.args(self.options.prove_client_args())
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped())
|
||||
.spawn()
|
||||
.and_then(
|
||||
|mut child| match child.wait_timeout(SHUTDOWN_SERVER_TIMEOUT)? {
|
||||
Some(_) => child.wait_with_output(),
|
||||
None => {
|
||||
child.kill().ok();
|
||||
Err(std::io::Error::other("shutdown command timed out"))
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
if result.as_ref().is_ok_and(|output| output.status.success()) {
|
||||
info!("Shutdown ZisK server");
|
||||
} else {
|
||||
error!(
|
||||
"Failed to shutdown ZisK server: {}",
|
||||
result
|
||||
.map(|output| String::from_utf8_lossy(&output.stderr).to_string())
|
||||
.unwrap_or_else(|err| err.to_string())
|
||||
);
|
||||
error!("Shutdown server child process and asm services manually...");
|
||||
let _ = self.child.kill();
|
||||
shutdown_asm_service(23115);
|
||||
shutdown_asm_service(23116);
|
||||
shutdown_asm_service(23117);
|
||||
remove_shm_files();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ZiskServer {
|
||||
/// Get status of server.
|
||||
pub fn status(&self, timeout: Duration) -> Result<ZiskServerStatus, Error> {
|
||||
let mut cmd = Command::new("cargo-zisk");
|
||||
let mut child = cmd
|
||||
.args(["prove-client", "status"])
|
||||
.args(self.options.prove_client_args())
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped())
|
||||
.spawn()
|
||||
.map_err(|err| CommonError::command(&cmd, err))?;
|
||||
|
||||
if child
|
||||
.wait_timeout(timeout)
|
||||
.map_err(|err| CommonError::command(&cmd, err))?
|
||||
.is_none()
|
||||
{
|
||||
// Timeout reached, kill the process
|
||||
child.kill().ok();
|
||||
return Err(Error::TimeoutWaitingServerReady);
|
||||
}
|
||||
|
||||
let output = child
|
||||
.wait_with_output()
|
||||
.map_err(|err| CommonError::command(&cmd, err))?;
|
||||
|
||||
if !output.status.success() {
|
||||
return Err(CommonError::command_exit_non_zero(
|
||||
&cmd,
|
||||
output.status,
|
||||
Some(&output),
|
||||
))?;
|
||||
}
|
||||
|
||||
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||
if stdout.contains("idle") {
|
||||
Ok(ZiskServerStatus::Idle)
|
||||
} else if stdout.contains("working") {
|
||||
Ok(ZiskServerStatus::Working)
|
||||
} else {
|
||||
Err(Error::UnknownServerStatus {
|
||||
stdout: stdout.to_string(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Send prove request to server and wait for proof to be created.
|
||||
pub fn prove(&mut self, input: &[u8]) -> Result<(PublicValues, Vec<u8>), Error> {
|
||||
// Prefix that ZisK server will add to the file name of the proof.
|
||||
// We use constant because the file will be save to a temporary dir,
|
||||
// so there will be no conflict.
|
||||
const PREFIX: &str = "ere";
|
||||
|
||||
let tempdir = tempdir().map_err(CommonError::tempdir)?;
|
||||
let input_path = tempdir.path().join("input");
|
||||
let output_path = tempdir.path().join("output");
|
||||
let proof_path = output_path.join(format!("{PREFIX}-vadcop_final_proof.bin"));
|
||||
|
||||
fs::write(&input_path, input)
|
||||
.map_err(|err| CommonError::write_file("input", &input_path, err))?;
|
||||
|
||||
// NOTE: Use snake case for `prove-client` command
|
||||
// Issue for tracking: https://github.com/eth-act/ere/issues/151.
|
||||
let mut cmd = Command::new("cargo-zisk");
|
||||
let output = cmd
|
||||
.args(["prove-client", "prove"])
|
||||
.arg("--input")
|
||||
.arg(input_path)
|
||||
.arg("--output_dir")
|
||||
.arg(&output_path)
|
||||
.args(["-p", PREFIX])
|
||||
.args(["--aggregation", "--verify_proofs"])
|
||||
.args(self.options.prove_args())
|
||||
.output()
|
||||
.map_err(|err| CommonError::command(&cmd, err))?;
|
||||
|
||||
if !output.status.success() {
|
||||
return Err(CommonError::command_exit_non_zero(
|
||||
&cmd,
|
||||
output.status,
|
||||
Some(&output),
|
||||
))?;
|
||||
}
|
||||
|
||||
// By default set 1 hour timeout for prove.
|
||||
let prove_timeout = env::var("ZISK_PROVE_TIMEOUT_SEC")
|
||||
.ok()
|
||||
.and_then(|timeout| timeout.parse::<u64>().ok())
|
||||
.map(Duration::from_secs)
|
||||
.unwrap_or(DEFAULT_PROVE_TIMEOUT);
|
||||
|
||||
// ZisK server will finish the `prove` requested above then respond the
|
||||
// following `status`. So if the following `status` succeeds, the proof
|
||||
// should also be ready.
|
||||
self.status(prove_timeout).map_err(|err| {
|
||||
if matches!(err, Error::TimeoutWaitingServerReady) {
|
||||
Error::TimeoutWaitingServerProving
|
||||
} else if err.to_string().contains("EOF") {
|
||||
Error::ServerCrashed
|
||||
} else {
|
||||
err
|
||||
}
|
||||
})?;
|
||||
|
||||
let proof = fs::read(&proof_path)
|
||||
.map_err(|err| CommonError::read_file("proof", &proof_path, err))?;
|
||||
|
||||
// Deserialize public values.
|
||||
let (proved_rom_digest, public_values) = deserialize_public_values(&proof)?;
|
||||
|
||||
// The proved ROM digest should be equal to preprocessed one.
|
||||
if proved_rom_digest != self.rom_digest {
|
||||
return Err(Error::UnexpectedRomDigest {
|
||||
preprocessed: self.rom_digest,
|
||||
proved: proved_rom_digest,
|
||||
});
|
||||
}
|
||||
|
||||
Ok((public_values, proof))
|
||||
}
|
||||
|
||||
/// Wait until the server status to be idle.
|
||||
fn wait_until_ready(&self) -> Result<(), Error> {
|
||||
const INTERVAL: Duration = Duration::from_secs(1);
|
||||
|
||||
info!("Waiting until server is ready...");
|
||||
|
||||
let start = Instant::now();
|
||||
while !matches!(
|
||||
self.status(START_SERVER_TIMEOUT),
|
||||
Ok(ZiskServerStatus::Idle)
|
||||
) {
|
||||
if start.elapsed() > START_SERVER_TIMEOUT {
|
||||
return Err(Error::TimeoutWaitingServerReady);
|
||||
}
|
||||
thread::sleep(INTERVAL);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Does global setup if it is not done yet.
|
||||
fn check_setup(cuda: bool) -> Result<(), Error> {
|
||||
info!("Running command `cargo-zisk check-setup --aggregation`...");
|
||||
@@ -588,42 +292,11 @@ fn rom_setup(elf_path: &Path) -> Result<RomDigest, Error> {
|
||||
Ok(rom_digest)
|
||||
}
|
||||
|
||||
/// Send shutdown request to ZisK asm services.
|
||||
fn shutdown_asm_service(port: u16) {
|
||||
// According to https://github.com/0xPolygonHermez/zisk/blob/v0.15.0/emulator-asm/asm-runner/src/asm_services/mod.rs#L34.
|
||||
const CMD_SHUTDOWN_REQUEST_ID: u64 = 1000000;
|
||||
if let Ok(mut stream) = TcpStream::connect((Ipv4Addr::LOCALHOST, port)) {
|
||||
let _ = stream.write_all(
|
||||
&[CMD_SHUTDOWN_REQUEST_ID, 0, 0, 0, 0]
|
||||
.into_iter()
|
||||
.flat_map(|word| word.to_le_bytes())
|
||||
.collect::<Vec<_>>(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove shared memory created by ZisK.
|
||||
fn remove_shm_files() {
|
||||
let Ok(shm_dir) = fs::read_dir(Path::new("/dev/shm")) else {
|
||||
return;
|
||||
};
|
||||
|
||||
for entry in shm_dir.flatten() {
|
||||
let path = entry.path();
|
||||
if path
|
||||
.file_name()
|
||||
.and_then(|n| n.to_str())
|
||||
.is_some_and(|name| name.starts_with("ZISK") || name.starts_with("sem"))
|
||||
{
|
||||
let _ = fs::remove_file(&path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Deserialize public values as json string sequence, and parse the `RomDigest`
|
||||
/// and user set public values as `Vec<u8>`.
|
||||
fn deserialize_public_values(proof: &[u8]) -> Result<(RomDigest, Vec<u8>), Error> {
|
||||
let proof = bytemuck::try_cast_slice::<_, u64>(proof).map_err(Error::CastProofBytesToU64s)?;
|
||||
let proof = align_to_u64(proof)?;
|
||||
let proof = bytemuck::cast_slice::<u8, u64>(&proof);
|
||||
|
||||
// The public values contain at least the the total number of public values,
|
||||
// `RomDigest`, and the number of user set public values.
|
||||
@@ -653,7 +326,23 @@ fn deserialize_public_values(proof: &[u8]) -> Result<(RomDigest, Vec<u8>), Error
|
||||
Ok((rom_digest, public_values))
|
||||
}
|
||||
|
||||
/// Returns u64-aligned bytes.
|
||||
///
|
||||
/// Returns an error if `data.len()` is not a multiple of 8.
|
||||
fn align_to_u64(data: &[u8]) -> Result<Cow<'_, [u8]>, Error> {
|
||||
if !data.len().is_multiple_of(8) {
|
||||
return Err(Error::InvalidProofSize(data.len()));
|
||||
}
|
||||
Ok(if data.as_ptr().cast::<u64>().is_aligned() {
|
||||
Cow::Borrowed(data)
|
||||
} else {
|
||||
let mut aligned: Vec<u64> = vec![0; data.len() / 8];
|
||||
bytemuck::cast_slice_mut(&mut aligned).copy_from_slice(data);
|
||||
Cow::Owned(bytemuck::cast_slice(&aligned).to_vec())
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns path to `~/.zisk` directory.
|
||||
fn dot_zisk_dir_path() -> PathBuf {
|
||||
pub(crate) fn dot_zisk_dir_path() -> PathBuf {
|
||||
PathBuf::from(env::var("HOME").expect("env `$HOME` should be set")).join(".zisk")
|
||||
}
|
||||
|
||||
461
crates/zkvm/zisk/src/zkvm/server.rs
Normal file
461
crates/zkvm/zisk/src/zkvm/server.rs
Normal file
@@ -0,0 +1,461 @@
|
||||
//! Local ZisK server management via `cargo-zisk` commands.
|
||||
|
||||
use crate::zkvm::{Error, sdk::dot_zisk_dir_path};
|
||||
use ere_zkvm_interface::zkvm::CommonError;
|
||||
use parking_lot::Mutex;
|
||||
use std::{
|
||||
collections::BTreeMap,
|
||||
env, fs,
|
||||
io::Write,
|
||||
iter,
|
||||
net::{Ipv4Addr, TcpStream},
|
||||
path::{Path, PathBuf},
|
||||
process::{Child, Command, Stdio},
|
||||
thread,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
use strum::{EnumIter, IntoEnumIterator};
|
||||
use tempfile::tempdir;
|
||||
use tracing::{error, info};
|
||||
use wait_timeout::ChildExt;
|
||||
|
||||
pub const DEFAULT_START_SERVER_TIMEOUT_SEC: u64 = 120; // 2 mins
|
||||
pub const DEFAULT_SHUTDOWN_SERVER_TIMEOUT_SEC: u64 = 30; // 30 secs
|
||||
pub const DEFAULT_PROVE_TIMEOUT_SEC: u64 = 3600; // 1 hour
|
||||
|
||||
/// ZisK server status returned from `cargo-zisk prove-client status`.
|
||||
#[derive(Debug)]
|
||||
pub enum ZiskServerStatus {
|
||||
Idle,
|
||||
Working,
|
||||
}
|
||||
|
||||
/// Options of `cargo-zisk` commands.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, EnumIter)]
|
||||
pub enum ZiskServerOption {
|
||||
Port,
|
||||
UnlockMappedMemory, // Should be set if locked memory is not enough
|
||||
MinimalMemory,
|
||||
// GPU options
|
||||
Preallocate, // Should be set only if GPU memory is enough
|
||||
SharedTables,
|
||||
MaxStreams,
|
||||
NumberThreadsWitness,
|
||||
MaxWitnessStored,
|
||||
}
|
||||
|
||||
impl ZiskServerOption {
|
||||
/// The key of the env variable to read from.
|
||||
fn env_var_key(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Port => "ERE_ZISK_PORT",
|
||||
Self::UnlockMappedMemory => "ERE_ZISK_UNLOCK_MAPPED_MEMORY",
|
||||
Self::MinimalMemory => "ERE_ZISK_MINIMAL_MEMORY",
|
||||
Self::Preallocate => "ERE_ZISK_PREALLOCATE",
|
||||
Self::SharedTables => "ERE_ZISK_SHARED_TABLES",
|
||||
Self::MaxStreams => "ERE_ZISK_MAX_STREAMS",
|
||||
Self::NumberThreadsWitness => "ERE_ZISK_NUMBER_THREADS_WITNESS",
|
||||
Self::MaxWitnessStored => "ERE_ZISK_MAX_WITNESS_STORED",
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether the option is a flag (false-by-default boolean option) or not.
|
||||
///
|
||||
/// When we read the option from env variable, if the option is a flag,
|
||||
/// we only check if the env variable is set or not.
|
||||
fn is_flag(&self) -> bool {
|
||||
match self {
|
||||
Self::UnlockMappedMemory
|
||||
| Self::MinimalMemory
|
||||
| Self::Preallocate
|
||||
| Self::SharedTables => true,
|
||||
Self::Port | Self::MaxStreams | Self::NumberThreadsWitness | Self::MaxWitnessStored => {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The option key to be appended to `cargo-zisk` command arguments.
|
||||
fn key(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Port => "--port",
|
||||
Self::UnlockMappedMemory => "--unlock-mapped-memory",
|
||||
// NOTE: Use snake case for `prove-client` command
|
||||
// Issue for tracking: https://github.com/eth-act/ere/issues/151.
|
||||
Self::MinimalMemory => "--minimal_memory",
|
||||
Self::Preallocate => "--preallocate",
|
||||
Self::SharedTables => "--shared-tables",
|
||||
Self::MaxStreams => "--max-streams",
|
||||
Self::NumberThreadsWitness => "--number-threads-witness",
|
||||
Self::MaxWitnessStored => "--max-witness-stored",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Configurable options for `cargo-zisk server` and `cargo-zisk prove-client` commands.
|
||||
#[derive(Clone)]
|
||||
pub struct ZiskServerOptions(BTreeMap<ZiskServerOption, String>);
|
||||
|
||||
impl ZiskServerOptions {
|
||||
/// Read options from env variables.
|
||||
pub fn from_env() -> Self {
|
||||
Self(
|
||||
ZiskServerOption::iter()
|
||||
.flat_map(|option| env::var(option.env_var_key()).ok().map(|val| (option, val)))
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns `cargo-zisk` command arguments by given options that have been
|
||||
/// set.
|
||||
fn args(
|
||||
&self,
|
||||
options: impl IntoIterator<Item = ZiskServerOption>,
|
||||
) -> impl Iterator<Item = &str> {
|
||||
options
|
||||
.into_iter()
|
||||
.filter(|option| self.0.contains_key(option))
|
||||
.flat_map(|option| {
|
||||
iter::once(option.key())
|
||||
.chain((!option.is_flag()).then(|| self.0[&option].as_str()))
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns `cargo-zisk server` command arguments.
|
||||
pub(crate) fn server_args(&self) -> impl Iterator<Item = &str> {
|
||||
self.args([
|
||||
ZiskServerOption::Port,
|
||||
ZiskServerOption::UnlockMappedMemory,
|
||||
ZiskServerOption::Preallocate,
|
||||
ZiskServerOption::SharedTables,
|
||||
ZiskServerOption::MaxStreams,
|
||||
ZiskServerOption::NumberThreadsWitness,
|
||||
ZiskServerOption::MaxWitnessStored,
|
||||
])
|
||||
}
|
||||
|
||||
/// Returns `cargo-zisk prove-client` command arguments.
|
||||
pub(crate) fn prove_client_args(&self) -> impl Iterator<Item = &str> {
|
||||
self.args([ZiskServerOption::Port])
|
||||
}
|
||||
|
||||
/// Returns `cargo-zisk prove-client prove` command arguments.
|
||||
pub(crate) fn prove_args(&self) -> impl Iterator<Item = &str> {
|
||||
self.prove_client_args()
|
||||
.chain(self.args([ZiskServerOption::MinimalMemory]))
|
||||
}
|
||||
}
|
||||
|
||||
/// Wrapper for ZisK server child process.
|
||||
pub struct ZiskServer {
|
||||
options: ZiskServerOptions,
|
||||
elf_path: PathBuf,
|
||||
cuda: bool,
|
||||
child: Mutex<Option<Child>>,
|
||||
}
|
||||
|
||||
impl Drop for ZiskServer {
|
||||
fn drop(&mut self) {
|
||||
self.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
impl ZiskServer {
|
||||
/// Create a new ZisK server for the given ELF.
|
||||
///
|
||||
/// The server process is lazily started on the first call to [`prove`](ZiskServer::prove).
|
||||
pub fn new(elf_path: &Path, cuda: bool, options: ZiskServerOptions) -> Self {
|
||||
Self {
|
||||
elf_path: elf_path.to_path_buf(),
|
||||
cuda,
|
||||
options,
|
||||
child: Mutex::new(None),
|
||||
}
|
||||
}
|
||||
|
||||
/// Send prove request to server and wait for proof to be created.
|
||||
///
|
||||
/// Returns the proof.
|
||||
pub fn prove(&self, input: &[u8]) -> Result<Vec<u8>, Error> {
|
||||
self.ensure_ready()?;
|
||||
|
||||
// Prefix that ZisK server will add to the file name of the proof.
|
||||
// We use constant because the file will be save to a temporary dir,
|
||||
// so there will be no conflict.
|
||||
const PREFIX: &str = "ere";
|
||||
|
||||
let tempdir = tempdir().map_err(CommonError::tempdir)?;
|
||||
let input_path = tempdir.path().join("input");
|
||||
let output_path = tempdir.path().join("output");
|
||||
let proof_path = output_path.join(format!("{PREFIX}-vadcop_final_proof.bin"));
|
||||
|
||||
fs::write(&input_path, input)
|
||||
.map_err(|err| CommonError::write_file("input", &input_path, err))?;
|
||||
|
||||
// NOTE: Use snake case for `prove-client` command
|
||||
// Issue for tracking: https://github.com/eth-act/ere/issues/151.
|
||||
let mut cmd = Command::new("cargo-zisk");
|
||||
let output = cmd
|
||||
.args(["prove-client", "prove"])
|
||||
.arg("--input")
|
||||
.arg(input_path)
|
||||
.arg("--output_dir")
|
||||
.arg(&output_path)
|
||||
.args(["-p", PREFIX])
|
||||
.args(["--aggregation", "--verify_proofs"])
|
||||
.args(self.options.prove_args())
|
||||
.output()
|
||||
.map_err(|err| CommonError::command(&cmd, err))?;
|
||||
|
||||
if !output.status.success() {
|
||||
return Err(CommonError::command_exit_non_zero(
|
||||
&cmd,
|
||||
output.status,
|
||||
Some(&output),
|
||||
))?;
|
||||
}
|
||||
|
||||
// ZisK server will finish the `prove` requested above then respond the
|
||||
// following `status`. So if the following `status` succeeds, the proof
|
||||
// should also be ready.
|
||||
self.status(prove_timeout()).map_err(|err| {
|
||||
if matches!(err, Error::TimeoutWaitingServerReady) {
|
||||
Error::TimeoutWaitingServerProving
|
||||
} else if err.to_string().contains("EOF") {
|
||||
Error::ServerCrashed
|
||||
} else {
|
||||
err
|
||||
}
|
||||
})?;
|
||||
|
||||
let proof = fs::read(&proof_path)
|
||||
.map_err(|err| CommonError::read_file("proof", &proof_path, err))?;
|
||||
|
||||
Ok(proof)
|
||||
}
|
||||
|
||||
/// Ensure the server is running and responsive, restarting it if needed.
|
||||
pub fn ensure_ready(&self) -> Result<(), Error> {
|
||||
if self.child.lock().is_some() && self.status(start_server_timeout()).is_ok() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
const MAX_RETRY: usize = 3;
|
||||
let mut attempt = 0;
|
||||
|
||||
loop {
|
||||
self.shutdown();
|
||||
match self.start() {
|
||||
Ok(()) => return Ok(()),
|
||||
Err(Error::TimeoutWaitingServerReady) if attempt < MAX_RETRY => {
|
||||
error!("Timeout waiting server ready, restarting...");
|
||||
attempt += 1;
|
||||
continue;
|
||||
}
|
||||
Err(err) => return Err(err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Spawn the server process and wait until it's ready.
|
||||
fn start(&self) -> Result<(), Error> {
|
||||
info!("Starting ZisK server...");
|
||||
|
||||
let (cargo_zisk, witness_lib_name) = if self.cuda {
|
||||
("cargo-zisk-cuda", "libzisk_witness_cuda.so")
|
||||
} else {
|
||||
("cargo-zisk", "libzisk_witness.so")
|
||||
};
|
||||
let witness_lib_path = dot_zisk_dir_path().join("bin").join(witness_lib_name);
|
||||
|
||||
let mut cmd = Command::new(cargo_zisk);
|
||||
cmd.arg("server")
|
||||
.args(self.options.server_args())
|
||||
.arg("--elf")
|
||||
.arg(&self.elf_path)
|
||||
.arg("--witness-lib")
|
||||
.arg(witness_lib_path)
|
||||
.arg("--aggregation");
|
||||
|
||||
let child = cmd.spawn().map_err(|err| CommonError::command(&cmd, err))?;
|
||||
|
||||
{
|
||||
let mut guard = self.child.lock();
|
||||
*guard = Some(child);
|
||||
}
|
||||
|
||||
self.wait_until_ready()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Wait until the server status to be idle.
|
||||
pub fn wait_until_ready(&self) -> Result<(), Error> {
|
||||
const INTERVAL: Duration = Duration::from_secs(1);
|
||||
|
||||
let timeout = start_server_timeout();
|
||||
|
||||
info!("Waiting until server is ready...");
|
||||
|
||||
let start = Instant::now();
|
||||
while !matches!(self.status(timeout), Ok(ZiskServerStatus::Idle)) {
|
||||
if start.elapsed() > timeout {
|
||||
return Err(Error::TimeoutWaitingServerReady);
|
||||
}
|
||||
thread::sleep(INTERVAL);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Gracefully shut down the server, falling back to force-kill on failure.
|
||||
fn shutdown(&self) {
|
||||
let mut guard = self.child.lock();
|
||||
let Some(mut child) = guard.take() else {
|
||||
return;
|
||||
};
|
||||
|
||||
info!("Shutting down ZisK server");
|
||||
|
||||
let mut cmd = Command::new("cargo-zisk");
|
||||
let result = cmd
|
||||
.args(["prove-client", "shutdown"])
|
||||
.args(self.options.prove_client_args())
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped())
|
||||
.spawn()
|
||||
.and_then(
|
||||
|mut child| match child.wait_timeout(shutdown_server_timeout())? {
|
||||
Some(_) => child.wait_with_output(),
|
||||
None => {
|
||||
child.kill().ok();
|
||||
Err(std::io::Error::other("shutdown command timed out"))
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
if result.as_ref().is_ok_and(|output| output.status.success()) {
|
||||
info!("Shutdown ZisK server");
|
||||
} else {
|
||||
error!(
|
||||
"Failed to shutdown ZisK server: {}",
|
||||
result
|
||||
.map(|output| String::from_utf8_lossy(&output.stderr).to_string())
|
||||
.unwrap_or_else(|err| err.to_string())
|
||||
);
|
||||
error!("Shutdown server child process and asm services manually...");
|
||||
let _ = child.kill();
|
||||
shutdown_asm_service(23115);
|
||||
shutdown_asm_service(23116);
|
||||
shutdown_asm_service(23117);
|
||||
remove_shm_files();
|
||||
}
|
||||
}
|
||||
|
||||
/// Get status of server.
|
||||
fn status(&self, timeout: Duration) -> Result<ZiskServerStatus, Error> {
|
||||
let mut cmd = Command::new("cargo-zisk");
|
||||
let mut child = cmd
|
||||
.args(["prove-client", "status"])
|
||||
.args(self.options.prove_client_args())
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped())
|
||||
.spawn()
|
||||
.map_err(|err| CommonError::command(&cmd, err))?;
|
||||
|
||||
if child
|
||||
.wait_timeout(timeout)
|
||||
.map_err(|err| CommonError::command(&cmd, err))?
|
||||
.is_none()
|
||||
{
|
||||
// Timeout reached, kill the process
|
||||
child.kill().ok();
|
||||
return Err(Error::TimeoutWaitingServerReady);
|
||||
}
|
||||
|
||||
let output = child
|
||||
.wait_with_output()
|
||||
.map_err(|err| CommonError::command(&cmd, err))?;
|
||||
|
||||
if !output.status.success() {
|
||||
return Err(CommonError::command_exit_non_zero(
|
||||
&cmd,
|
||||
output.status,
|
||||
Some(&output),
|
||||
))?;
|
||||
}
|
||||
|
||||
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||
if stdout.contains("idle") {
|
||||
Ok(ZiskServerStatus::Idle)
|
||||
} else if stdout.contains("working") {
|
||||
Ok(ZiskServerStatus::Working)
|
||||
} else {
|
||||
Err(Error::UnknownServerStatus {
|
||||
stdout: stdout.to_string(),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Send shutdown request to ZisK asm services.
|
||||
fn shutdown_asm_service(port: u16) {
|
||||
// According to https://github.com/0xPolygonHermez/zisk/blob/v0.15.0/emulator-asm/asm-runner/src/asm_services/mod.rs#L34.
|
||||
const CMD_SHUTDOWN_REQUEST_ID: u64 = 1000000;
|
||||
if let Ok(mut stream) = TcpStream::connect((Ipv4Addr::LOCALHOST, port)) {
|
||||
let _ = stream.write_all(
|
||||
&[CMD_SHUTDOWN_REQUEST_ID, 0, 0, 0, 0]
|
||||
.into_iter()
|
||||
.flat_map(|word| word.to_le_bytes())
|
||||
.collect::<Vec<_>>(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove shared memory created by ZisK.
|
||||
fn remove_shm_files() {
|
||||
let Ok(shm_dir) = fs::read_dir(Path::new("/dev/shm")) else {
|
||||
return;
|
||||
};
|
||||
|
||||
for entry in shm_dir.flatten() {
|
||||
let path = entry.path();
|
||||
if path
|
||||
.file_name()
|
||||
.and_then(|n| n.to_str())
|
||||
.is_some_and(|name| name.starts_with("ZISK") || name.starts_with("sem"))
|
||||
{
|
||||
let _ = fs::remove_file(&path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the server start timeout, configurable via `ERE_ZISK_START_SERVER_TIMEOUT_SEC`.
|
||||
fn start_server_timeout() -> Duration {
|
||||
timeout(
|
||||
"ERE_ZISK_START_SERVER_TIMEOUT_SEC",
|
||||
DEFAULT_START_SERVER_TIMEOUT_SEC,
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns the server shutdown timeout, configurable via `ERE_ZISK_SHUTDOWN_SERVER_TIMEOUT_SEC`.
|
||||
fn shutdown_server_timeout() -> Duration {
|
||||
timeout(
|
||||
"ERE_ZISK_SHUTDOWN_SERVER_TIMEOUT_SEC",
|
||||
DEFAULT_SHUTDOWN_SERVER_TIMEOUT_SEC,
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns the prove timeout, configurable via `ERE_ZISK_PROVE_TIMEOUT_SEC`.
|
||||
fn prove_timeout() -> Duration {
|
||||
timeout("ERE_ZISK_PROVE_TIMEOUT_SEC", DEFAULT_PROVE_TIMEOUT_SEC)
|
||||
}
|
||||
|
||||
/// Read a timeout from the given env variable key, falling back to `default`.
|
||||
fn timeout(key: &str, default: u64) -> Duration {
|
||||
let sec = env::var(key)
|
||||
.ok()
|
||||
.and_then(|timeout| timeout.parse::<u64>().ok())
|
||||
.unwrap_or(default);
|
||||
Duration::from_secs(sec)
|
||||
}
|
||||
114
docker/zisk/Dockerfile.cluster
Normal file
114
docker/zisk/Dockerfile.cluster
Normal file
@@ -0,0 +1,114 @@
|
||||
ARG BASE_IMAGE=ubuntu:24.04
|
||||
ARG BASE_CUDA_IMAGE=nvidia/cuda:12.9.1-devel-ubuntu24.04
|
||||
ARG RUNTIME_IMAGE=ubuntu:24.04
|
||||
ARG RUNTIME_CUDA_IMAGE=nvidia/cuda:12.9.1-runtime-ubuntu24.04
|
||||
|
||||
# Whether to enable CUDA feature or not.
|
||||
ARG CUDA
|
||||
|
||||
FROM $BASE_IMAGE AS base
|
||||
FROM $BASE_CUDA_IMAGE AS base_cuda
|
||||
FROM base${CUDA:+_cuda} AS build_stage
|
||||
|
||||
# Taken from https://0xpolygonhermez.github.io/zisk/getting_started/installation.html
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
git \
|
||||
xz-utils \
|
||||
jq \
|
||||
curl \
|
||||
build-essential \
|
||||
qemu-system \
|
||||
libomp-dev \
|
||||
libgmp-dev \
|
||||
nlohmann-json3-dev \
|
||||
protobuf-compiler \
|
||||
uuid-dev \
|
||||
libgrpc++-dev \
|
||||
libsecp256k1-dev \
|
||||
libsodium-dev \
|
||||
libpqxx-dev \
|
||||
nasm \
|
||||
libopenmpi-dev \
|
||||
openmpi-bin \
|
||||
openmpi-common \
|
||||
libclang-dev \
|
||||
clang \
|
||||
gcc-riscv64-unknown-elf \
|
||||
libprotobuf-dev \
|
||||
&& apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install rustup
|
||||
ARG RUST_VERSION=1.88.0
|
||||
|
||||
ENV RUSTUP_HOME=/usr/local/rustup \
|
||||
CARGO_HOME=/usr/local/cargo \
|
||||
PATH=/usr/local/cargo/bin:$PATH
|
||||
|
||||
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain ${RUST_VERSION} --no-modify-path
|
||||
|
||||
# Clone repo
|
||||
WORKDIR /app
|
||||
|
||||
RUN git clone https://github.com/han0110/zisk.git --depth 1 --branch patch/v0.15.0-cluster /app
|
||||
|
||||
# Whether to enable CUDA feature or not.
|
||||
ARG CUDA
|
||||
|
||||
# Default to build for RTX 50 series
|
||||
ARG CUDA_ARCH=sm_120
|
||||
|
||||
# Build binaries
|
||||
RUN cargo build --release ${CUDA:+--features gpu}
|
||||
|
||||
FROM $RUNTIME_IMAGE AS runtime
|
||||
FROM $RUNTIME_CUDA_IMAGE AS runtime_cuda
|
||||
FROM runtime${CUDA:+_cuda} AS runtime_stage
|
||||
|
||||
# Taken from https://0xpolygonhermez.github.io/zisk/getting_started/installation.html
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
xz-utils \
|
||||
jq \
|
||||
curl \
|
||||
build-essential \
|
||||
qemu-system \
|
||||
libomp-dev \
|
||||
libgmp-dev \
|
||||
nlohmann-json3-dev \
|
||||
protobuf-compiler \
|
||||
uuid-dev \
|
||||
libgrpc++-dev \
|
||||
libsecp256k1-dev \
|
||||
libsodium-dev \
|
||||
libpqxx-dev \
|
||||
nasm \
|
||||
libopenmpi-dev \
|
||||
openmpi-bin \
|
||||
openmpi-common \
|
||||
libclang-dev \
|
||||
clang \
|
||||
gcc-riscv64-unknown-elf \
|
||||
libprotobuf-dev \
|
||||
&& apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN curl -sSL https://github.com/fullstorydev/grpcurl/releases/download/v1.9.3/grpcurl_1.9.3_linux_x86_64.tar.gz \
|
||||
| tar -xz -C /usr/local/bin grpcurl
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Copy script
|
||||
COPY --from=build_stage /app/ziskup/ziskup /app/ziskup/ziskup
|
||||
|
||||
# Copy binaries (to /usr/local/bin instead of ~/.zisk/bin because we want to mount ~/.zisk later)
|
||||
COPY --from=build_stage /app/target/release/cargo-zisk /usr/local/bin/cargo-zisk
|
||||
COPY --from=build_stage /app/target/release/libzisk_witness.so /usr/local/bin/libzisk_witness.so
|
||||
COPY --from=build_stage /app/target/release/zisk-coordinator /usr/local/bin/zisk-coordinator
|
||||
COPY --from=build_stage /app/target/release/zisk-worker /usr/local/bin/zisk-worker
|
||||
|
||||
# Copy proto for health check
|
||||
COPY --from=build_stage /app/distributed/crates/grpc-api/proto/zisk_distributed_api.proto /app/proto/zisk_distributed_api.proto
|
||||
|
||||
# Copy configs
|
||||
COPY --from=build_stage /app/distributed/crates/coordinator/config/ /app/config/coordinator/
|
||||
COPY --from=build_stage /app/distributed/crates/worker/config/ /app/config/worker/
|
||||
|
||||
CMD ["/bin/bash"]
|
||||
131
examples/zisk/docker-compose.cluster.yml
Normal file
131
examples/zisk/docker-compose.cluster.yml
Normal file
@@ -0,0 +1,131 @@
|
||||
services:
|
||||
zisk-setup:
|
||||
image: ere-cluster-zisk:local-cuda
|
||||
entrypoint: ["/bin/bash", "-c"]
|
||||
command:
|
||||
- |
|
||||
set -e
|
||||
|
||||
if [ ! -d "/root/.zisk/provingKey" ]; then
|
||||
echo "Install rustup temporarily for ziskup..."
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain none
|
||||
source "$$HOME/.cargo/env"
|
||||
|
||||
echo "Download proving key..."
|
||||
SETUP_KEY=proving-no-consttree /app/ziskup/ziskup
|
||||
|
||||
echo "Cleaning up rustup, cargo, toolchains and binaries..."
|
||||
rustup self uninstall -y
|
||||
rm -rf /root/.zisk/toolchains
|
||||
rm /root/.zisk/bin/cargo-zisk
|
||||
rm /root/.zisk/bin/libzisk_witness.so
|
||||
rm /root/.zisk/bin/riscv2zisk
|
||||
rm /root/.zisk/bin/zisk-coordinator
|
||||
rm /root/.zisk/bin/ziskemu
|
||||
rm /root/.zisk/bin/ziskup
|
||||
rm /root/.zisk/bin/zisk-worker
|
||||
|
||||
echo "Generating constant tree files (GPU). This may take a while..."
|
||||
cargo-zisk check-setup -a
|
||||
else
|
||||
echo "Proving key already exists, skipping"
|
||||
fi
|
||||
|
||||
echo "Running rom-setup..."
|
||||
cargo-zisk rom-setup -e /app/elf
|
||||
|
||||
echo "Setup complete"
|
||||
volumes:
|
||||
- zisk_setup:/root/.zisk
|
||||
- ${ELF_PATH}:/app/elf:ro
|
||||
deploy:
|
||||
resources:
|
||||
reservations:
|
||||
devices:
|
||||
- driver: nvidia
|
||||
device_ids: ['0']
|
||||
capabilities: [gpu]
|
||||
|
||||
zisk-coordinator:
|
||||
image: ere-cluster-zisk:local-cuda
|
||||
command:
|
||||
- "zisk-coordinator"
|
||||
- "--config"
|
||||
- "/app/config/coordinator/prod.toml"
|
||||
ports:
|
||||
- "50051:50051"
|
||||
# volumes:
|
||||
# Uncomment to override config
|
||||
# - ./coordinator-config:/app/config/coordinator/prod.toml:ro
|
||||
environment:
|
||||
- RUST_LOG=info
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: ["CMD", "grpcurl", "-plaintext", "-import-path", "/app/proto", "-proto", "zisk_distributed_api.proto", "localhost:50051", "zisk.distributed.api.v1.ZiskDistributedApi/HealthCheck"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 10s
|
||||
|
||||
zisk-worker-0:
|
||||
image: ere-cluster-zisk:local-cuda
|
||||
command:
|
||||
- "zisk-worker"
|
||||
- "--config"
|
||||
- "/app/config/worker/prod.toml"
|
||||
- "--coordinator-url"
|
||||
- "http://zisk-coordinator:50051"
|
||||
- "--elf"
|
||||
- "/app/elf"
|
||||
- "--witness-lib"
|
||||
- "/usr/local/bin/libzisk_witness.so"
|
||||
volumes:
|
||||
# Mount proving key
|
||||
- zisk_setup:/root/.zisk:ro
|
||||
# Mount ELF
|
||||
- ${ELF_PATH}:/app/elf:ro
|
||||
# Uncomment to override config
|
||||
# - ./worker-config:/app/config/worker/prod.toml:ro
|
||||
environment:
|
||||
- RUST_LOG=info
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
zisk-setup:
|
||||
condition: service_completed_successfully
|
||||
zisk-coordinator:
|
||||
condition: service_healthy
|
||||
shm_size: 32G
|
||||
ulimits:
|
||||
memlock:
|
||||
soft: -1
|
||||
hard: -1
|
||||
healthcheck:
|
||||
test: ["CMD", "pgrep", "-f", "zisk-worker"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 60s
|
||||
deploy:
|
||||
resources:
|
||||
reservations:
|
||||
devices:
|
||||
- driver: nvidia
|
||||
device_ids: ['0']
|
||||
capabilities: [gpu]
|
||||
|
||||
# Uncomment to add more workers if more GPUs are available.
|
||||
# zisk-worker-x:
|
||||
# extends: zisk-worker-0
|
||||
# deploy:
|
||||
# resources:
|
||||
# reservations:
|
||||
# devices:
|
||||
# - driver: nvidia
|
||||
# device_ids: ['x']
|
||||
# capabilities: [gpu]
|
||||
|
||||
volumes:
|
||||
zisk_setup:
|
||||
|
||||
networks:
|
||||
default:
|
||||
Reference in New Issue
Block a user