mirror of
https://github.com/eth-act/ere.git
synced 2026-02-19 11:54:42 -05:00
Integrate Airbender (#175)
This commit is contained in:
18
.github/workflows/test-zkvm-airbender.yml
vendored
Normal file
18
.github/workflows/test-zkvm-airbender.yml
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
name: Test and clippy Airbender
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
test:
|
||||
uses: ./.github/workflows/test-zkvm.yml
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
with:
|
||||
zkvm: airbender
|
||||
toolchain: nightly
|
||||
skip_prove_test: true
|
||||
16
.github/workflows/test-zkvm.yml
vendored
16
.github/workflows/test-zkvm.yml
vendored
@@ -173,7 +173,8 @@ jobs:
|
||||
--rm \
|
||||
--interactive \
|
||||
--volume ${{ github.workspace }}:/ere \
|
||||
--volume $HOME/.cargo:/root/.cargo \
|
||||
--volume $HOME/.cargo/registry:/usr/local/cargo/registry \
|
||||
--volume $HOME/.cargo/git:/usr/local/cargo/git \
|
||||
--workdir /ere \
|
||||
${{ needs.build_image.outputs.base_zkvm_image }} \
|
||||
/bin/bash"
|
||||
@@ -186,8 +187,9 @@ jobs:
|
||||
cargo clippy --package ere-compiler --features ${{ inputs.zkvm }} \$OPTIONS
|
||||
cargo clippy --package ere-server --features ${{ inputs.zkvm }} \$OPTIONS
|
||||
|
||||
chown -R $(id -u):$(id -g) ~/.cargo
|
||||
chown -R $(id -u):$(id -g) target
|
||||
time chown -R $(id -u):$(id -g) /usr/local/cargo/registry
|
||||
time chown -R $(id -u):$(id -g) /usr/local/cargo/git
|
||||
time chown -R $(id -u):$(id -g) target
|
||||
EOF
|
||||
|
||||
test_via_docker:
|
||||
@@ -221,7 +223,8 @@ jobs:
|
||||
--rm \
|
||||
--interactive \
|
||||
--volume ${{ github.workspace }}:/ere \
|
||||
--volume $HOME/.cargo:/root/.cargo \
|
||||
--volume $HOME/.cargo/registry:/usr/local/cargo/registry \
|
||||
--volume $HOME/.cargo/git:/usr/local/cargo/git \
|
||||
--workdir /ere \
|
||||
${{ needs.build_image.outputs.base_zkvm_image }} \
|
||||
/bin/bash"
|
||||
@@ -232,8 +235,9 @@ jobs:
|
||||
cargo test --release --package ere-${{ inputs.zkvm }} \
|
||||
-- ${{ inputs.skip_prove_test && '--skip prove' || '' }}
|
||||
|
||||
chown -R $(id -u):$(id -g) ~/.cargo
|
||||
chown -R $(id -u):$(id -g) target
|
||||
time chown -R $(id -u):$(id -g) /usr/local/cargo/registry
|
||||
time chown -R $(id -u):$(id -g) /usr/local/cargo/git
|
||||
time chown -R $(id -u):$(id -g) target
|
||||
EOF
|
||||
|
||||
test_ere_dockerized:
|
||||
|
||||
570
Cargo.lock
generated
570
Cargo.lock
generated
@@ -23,6 +23,21 @@ dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
version = "0.22.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678"
|
||||
dependencies = [
|
||||
"cpp_demangle",
|
||||
"fallible-iterator",
|
||||
"gimli 0.29.0",
|
||||
"memmap2",
|
||||
"object 0.35.0",
|
||||
"rustc-demangle",
|
||||
"smallvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
version = "0.24.2"
|
||||
@@ -31,9 +46,9 @@ checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1"
|
||||
dependencies = [
|
||||
"cpp_demangle",
|
||||
"fallible-iterator",
|
||||
"gimli",
|
||||
"gimli 0.31.1",
|
||||
"memmap2",
|
||||
"object",
|
||||
"object 0.36.7",
|
||||
"rustc-demangle",
|
||||
"smallvec",
|
||||
"typed-arena",
|
||||
@@ -63,6 +78,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"const-random",
|
||||
"getrandom 0.3.3",
|
||||
"once_cell",
|
||||
"version_check",
|
||||
"zerocopy",
|
||||
@@ -1851,11 +1868,11 @@ version = "0.3.75"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002"
|
||||
dependencies = [
|
||||
"addr2line",
|
||||
"addr2line 0.24.2",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"miniz_oxide",
|
||||
"object",
|
||||
"object 0.36.7",
|
||||
"rustc-demangle",
|
||||
"serde",
|
||||
"windows-targets 0.52.6",
|
||||
@@ -1928,6 +1945,17 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bigint_with_control"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/matter-labs/zksync-airbender?tag=v0.5.0#a3c74040d2f994608f451550232392333400bbf1"
|
||||
dependencies = [
|
||||
"prover",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"verifier_generator",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bincode"
|
||||
version = "1.3.3"
|
||||
@@ -2103,6 +2131,17 @@ dependencies = [
|
||||
"digest 0.10.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "blake2_with_compression"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/matter-labs/zksync-airbender?tag=v0.5.0#a3c74040d2f994608f451550232392333400bbf1"
|
||||
dependencies = [
|
||||
"prover",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"verifier_generator",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "blake2b_simd"
|
||||
version = "1.0.3"
|
||||
@@ -2114,6 +2153,14 @@ dependencies = [
|
||||
"constant_time_eq 0.3.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "blake2s_u32"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/matter-labs/zksync-airbender?tag=v0.5.0#a3c74040d2f994608f451550232392333400bbf1"
|
||||
dependencies = [
|
||||
"unroll",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "blake3"
|
||||
version = "1.8.2"
|
||||
@@ -2443,6 +2490,16 @@ dependencies = [
|
||||
"inout",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "circuit_common"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/matter-labs/zksync-airbender?tag=v0.5.0#a3c74040d2f994608f451550232392333400bbf1"
|
||||
dependencies = [
|
||||
"fft",
|
||||
"field",
|
||||
"worker",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clang-sys"
|
||||
version = "1.8.1"
|
||||
@@ -2612,6 +2669,26 @@ version = "0.9.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
|
||||
|
||||
[[package]]
|
||||
name = "const-random"
|
||||
version = "0.1.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359"
|
||||
dependencies = [
|
||||
"const-random-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "const-random-macro"
|
||||
version = "0.1.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e"
|
||||
dependencies = [
|
||||
"getrandom 0.2.16",
|
||||
"once_cell",
|
||||
"tiny-keccak",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "const_format"
|
||||
version = "0.2.34"
|
||||
@@ -2859,6 +2936,31 @@ dependencies = [
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cs"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/matter-labs/zksync-airbender?tag=v0.5.0#a3c74040d2f994608f451550232392333400bbf1"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"bincode 1.3.3",
|
||||
"blake2s_u32",
|
||||
"derivative",
|
||||
"divrem",
|
||||
"field",
|
||||
"itertools 0.14.0",
|
||||
"poseidon2",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rayon",
|
||||
"seq-macro",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"smallvec",
|
||||
"super-seq-macro",
|
||||
"syn 2.0.101",
|
||||
"type-map",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "csv"
|
||||
version = "1.3.1"
|
||||
@@ -3347,6 +3449,12 @@ version = "1.0.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8975ffdaa0ef3661bfe02dbdcc06c9f829dfafe6a3c474de366a8d5e44276921"
|
||||
|
||||
[[package]]
|
||||
name = "divrem"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "69dde51e8fef5e12c1d65e0929b03d66e4c0c18282bc30ed2ca050ad6f44dd82"
|
||||
|
||||
[[package]]
|
||||
name = "docker-generate"
|
||||
version = "0.1.3"
|
||||
@@ -3619,6 +3727,21 @@ dependencies = [
|
||||
"typeid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ere-airbender"
|
||||
version = "0.0.14"
|
||||
dependencies = [
|
||||
"bincode 2.0.1",
|
||||
"ere-build-utils",
|
||||
"ere-compile-utils",
|
||||
"ere-test-utils",
|
||||
"ere-zkvm-interface",
|
||||
"execution_utils",
|
||||
"serde_json",
|
||||
"tempfile",
|
||||
"thiserror 2.0.12",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ere-build-utils"
|
||||
version = "0.0.14"
|
||||
@@ -3644,6 +3767,7 @@ dependencies = [
|
||||
"anyhow",
|
||||
"bincode 2.0.1",
|
||||
"clap",
|
||||
"ere-airbender",
|
||||
"ere-jolt",
|
||||
"ere-miden",
|
||||
"ere-nexus",
|
||||
@@ -3796,6 +3920,7 @@ dependencies = [
|
||||
"anyhow",
|
||||
"bincode 2.0.1",
|
||||
"clap",
|
||||
"ere-airbender",
|
||||
"ere-jolt",
|
||||
"ere-miden",
|
||||
"ere-nexus",
|
||||
@@ -4227,6 +4352,19 @@ dependencies = [
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "execution_utils"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/matter-labs/zksync-airbender?tag=v0.5.0#a3c74040d2f994608f451550232392333400bbf1"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"risc_v_simulator",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"trace_and_split",
|
||||
"verifier_common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "eyre"
|
||||
version = "0.6.12"
|
||||
@@ -4310,12 +4448,48 @@ dependencies = [
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fft"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/matter-labs/zksync-airbender?tag=v0.5.0#a3c74040d2f994608f451550232392333400bbf1"
|
||||
dependencies = [
|
||||
"field",
|
||||
"itertools 0.14.0",
|
||||
"rayon",
|
||||
"seq-macro",
|
||||
"trace_holder",
|
||||
"unroll",
|
||||
"worker",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fiat-crypto"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d"
|
||||
|
||||
[[package]]
|
||||
name = "field"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/matter-labs/zksync-airbender?tag=v0.5.0#a3c74040d2f994608f451550232392333400bbf1"
|
||||
dependencies = [
|
||||
"rand 0.9.2",
|
||||
"seq-macro",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "final_reduced_risc_v_machine"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/matter-labs/zksync-airbender?tag=v0.5.0#a3c74040d2f994608f451550232392333400bbf1"
|
||||
dependencies = [
|
||||
"circuit_common",
|
||||
"prover",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"verifier_generator",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "findshlibs"
|
||||
version = "0.10.2"
|
||||
@@ -4692,6 +4866,16 @@ dependencies = [
|
||||
"syn 2.0.101",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.29.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd"
|
||||
dependencies = [
|
||||
"fallible-iterator",
|
||||
"stable_deref_trait",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.31.1"
|
||||
@@ -5549,6 +5733,28 @@ dependencies = [
|
||||
"web-time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inferno"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e96d2465363ed2d81857759fc864cf6bb7997f79327aec028d65bd7989393685"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"clap",
|
||||
"crossbeam-channel",
|
||||
"crossbeam-utils",
|
||||
"dashmap",
|
||||
"env_logger",
|
||||
"indexmap 2.10.0",
|
||||
"itoa",
|
||||
"log",
|
||||
"num-format",
|
||||
"once_cell",
|
||||
"quick-xml",
|
||||
"rgb",
|
||||
"str_stack",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inout"
|
||||
version = "0.1.4"
|
||||
@@ -5969,6 +6175,20 @@ version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
||||
|
||||
[[package]]
|
||||
name = "lib-rv32-asm"
|
||||
version = "0.2.0"
|
||||
source = "git+https://github.com/shamatar/lib-rv32.git#869f82795f82314f17014a04fb6f2c31808e6b42"
|
||||
dependencies = [
|
||||
"lib-rv32-common",
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lib-rv32-common"
|
||||
version = "0.2.0"
|
||||
source = "git+https://github.com/shamatar/lib-rv32.git#869f82795f82314f17014a04fb6f2c31808e6b42"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.175"
|
||||
@@ -6128,6 +6348,18 @@ version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154"
|
||||
|
||||
[[package]]
|
||||
name = "machine_without_signed_mul_div"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/matter-labs/zksync-airbender?tag=v0.5.0#a3c74040d2f994608f451550232392333400bbf1"
|
||||
dependencies = [
|
||||
"circuit_common",
|
||||
"prover",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"verifier_generator",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "macro-string"
|
||||
version = "0.1.4"
|
||||
@@ -6868,6 +7100,11 @@ dependencies = [
|
||||
"minimal-lexical",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "non_determinism_source"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/matter-labs/zksync-airbender?tag=v0.5.0#a3c74040d2f994608f451550232392333400bbf1"
|
||||
|
||||
[[package]]
|
||||
name = "ntapi"
|
||||
version = "0.4.1"
|
||||
@@ -6967,6 +7204,16 @@ dependencies = [
|
||||
"syn 2.0.101",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-format"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"itoa",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.46"
|
||||
@@ -7161,6 +7408,17 @@ dependencies = [
|
||||
"malloc_buf",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.35.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8ec7ab813848ba4522158d5517a6093db1ded27575b070f4177b8d12b41db5e"
|
||||
dependencies = [
|
||||
"flate2",
|
||||
"memchr",
|
||||
"ruzstd 0.6.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.36.7"
|
||||
@@ -7172,7 +7430,7 @@ dependencies = [
|
||||
"hashbrown 0.15.3",
|
||||
"indexmap 2.10.0",
|
||||
"memchr",
|
||||
"ruzstd",
|
||||
"ruzstd 0.7.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -7180,6 +7438,9 @@ name = "once_cell"
|
||||
version = "1.21.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
||||
dependencies = [
|
||||
"portable-atomic",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "open-fastrlp"
|
||||
@@ -9919,6 +10180,17 @@ dependencies = [
|
||||
"portable-atomic",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "poseidon2"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/matter-labs/zksync-airbender?tag=v0.5.0#a3c74040d2f994608f451550232392333400bbf1"
|
||||
dependencies = [
|
||||
"field",
|
||||
"non_determinism_source",
|
||||
"rand 0.9.2",
|
||||
"unroll",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "postcard"
|
||||
version = "1.1.1"
|
||||
@@ -10282,6 +10554,34 @@ dependencies = [
|
||||
"prost 0.13.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prover"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/matter-labs/zksync-airbender?tag=v0.5.0#a3c74040d2f994608f451550232392333400bbf1"
|
||||
dependencies = [
|
||||
"bit-set 0.8.0",
|
||||
"blake2s_u32",
|
||||
"cs",
|
||||
"fft",
|
||||
"field",
|
||||
"itertools 0.14.0",
|
||||
"lib-rv32-asm",
|
||||
"non_determinism_source",
|
||||
"poseidon2",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rayon",
|
||||
"risc_v_simulator",
|
||||
"seq-macro",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"syn 2.0.101",
|
||||
"trace_holder",
|
||||
"transcript",
|
||||
"unroll",
|
||||
"worker",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "puffin"
|
||||
version = "0.19.1"
|
||||
@@ -10317,6 +10617,15 @@ version = "1.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
|
||||
|
||||
[[package]]
|
||||
name = "quick-xml"
|
||||
version = "0.37.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "331e97a1af0bf59823e6eadffe373d7b27f485be8748f71471c662c1f269b7fb"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quinn"
|
||||
version = "0.11.8"
|
||||
@@ -10621,6 +10930,30 @@ dependencies = [
|
||||
"thiserror 2.0.12",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "reduced_risc_v_log_23_machine"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/matter-labs/zksync-airbender?tag=v0.5.0#a3c74040d2f994608f451550232392333400bbf1"
|
||||
dependencies = [
|
||||
"circuit_common",
|
||||
"prover",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"verifier_generator",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "reduced_risc_v_machine"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/matter-labs/zksync-airbender?tag=v0.5.0#a3c74040d2f994608f451550232392333400bbf1"
|
||||
dependencies = [
|
||||
"circuit_common",
|
||||
"prover",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"verifier_generator",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.11.1"
|
||||
@@ -10798,6 +11131,43 @@ dependencies = [
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rgb"
|
||||
version = "0.8.52"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c6a884d2998352bb4daf0183589aec883f16a6da1f4dde84d8e2e9a5409a1ce"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rhai"
|
||||
version = "1.23.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "527390cc333a8d2cd8237890e15c36518c26f8b54c903d86fc59f42f08d25594"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"bitflags 2.9.0",
|
||||
"instant",
|
||||
"num-traits",
|
||||
"once_cell",
|
||||
"rhai_codegen",
|
||||
"smallvec",
|
||||
"smartstring",
|
||||
"thin-vec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rhai_codegen"
|
||||
version = "3.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4322a2a4e8cf30771dd9f27f7f37ca9ac8fe812dddd811096a98483080dabe6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.101",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ring"
|
||||
version = "0.16.20"
|
||||
@@ -11120,7 +11490,7 @@ version = "3.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fcce11648a9ff60b8e7af2f0ce7fbf8d25275ab6d414cc91b9da69ee75bc978"
|
||||
dependencies = [
|
||||
"addr2line",
|
||||
"addr2line 0.24.2",
|
||||
"anyhow",
|
||||
"bincode 1.3.3",
|
||||
"borsh",
|
||||
@@ -11131,13 +11501,13 @@ dependencies = [
|
||||
"enum-map",
|
||||
"gdbstub",
|
||||
"gdbstub_arch",
|
||||
"gimli",
|
||||
"gimli 0.31.1",
|
||||
"hex",
|
||||
"keccak",
|
||||
"lazy-regex",
|
||||
"num-bigint 0.4.6",
|
||||
"num-traits",
|
||||
"object",
|
||||
"object 0.36.7",
|
||||
"prost 0.13.5",
|
||||
"rand 0.9.2",
|
||||
"rayon",
|
||||
@@ -11179,6 +11549,37 @@ dependencies = [
|
||||
"stability",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "risc_v_cycles"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/matter-labs/zksync-airbender?tag=v0.5.0#a3c74040d2f994608f451550232392333400bbf1"
|
||||
dependencies = [
|
||||
"circuit_common",
|
||||
"prover",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"verifier_generator",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "risc_v_simulator"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/matter-labs/zksync-airbender?tag=v0.5.0#a3c74040d2f994608f451550232392333400bbf1"
|
||||
dependencies = [
|
||||
"addr2line 0.22.0",
|
||||
"blake2s_u32",
|
||||
"cs",
|
||||
"field",
|
||||
"inferno",
|
||||
"memmap2",
|
||||
"object 0.36.7",
|
||||
"poseidon2",
|
||||
"rand 0.9.2",
|
||||
"ringbuffer",
|
||||
"ruint",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rlp"
|
||||
version = "0.5.2"
|
||||
@@ -11517,6 +11918,17 @@ dependencies = [
|
||||
"wait-timeout",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruzstd"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5174a470eeb535a721ae9fdd6e291c2411a906b96592182d05217591d5c5cf7b"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"derive_more 0.99.20",
|
||||
"twox-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruzstd"
|
||||
version = "0.7.3"
|
||||
@@ -11786,6 +12198,12 @@ version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73"
|
||||
|
||||
[[package]]
|
||||
name = "seq-macro"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1bc711410fbe7399f390ca1c3b60ad0f53f80e95c5eb935e52268a0e2cd49acc"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.221"
|
||||
@@ -11960,6 +12378,27 @@ dependencies = [
|
||||
"syn 2.0.101",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "setups"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/matter-labs/zksync-airbender?tag=v0.5.0#a3c74040d2f994608f451550232392333400bbf1"
|
||||
dependencies = [
|
||||
"bigint_with_control",
|
||||
"blake2_with_compression",
|
||||
"final_reduced_risc_v_machine",
|
||||
"machine_without_signed_mul_div",
|
||||
"proc-macro2",
|
||||
"prover",
|
||||
"quote",
|
||||
"reduced_risc_v_log_23_machine",
|
||||
"reduced_risc_v_machine",
|
||||
"risc_v_cycles",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"syn 2.0.101",
|
||||
"verifier_common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha1"
|
||||
version = "0.10.6"
|
||||
@@ -12090,6 +12529,17 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "smartstring"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fb72c633efbaa2dd666986505016c32c3044395ceaf881518399d2f4127ee29"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"static_assertions",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "smawk"
|
||||
version = "0.3.2"
|
||||
@@ -12688,6 +13138,12 @@ version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||
|
||||
[[package]]
|
||||
name = "str_stack"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9091b6114800a5f2141aee1d1b9d6ca3592ac062dc5decb3764ec5895a47b4eb"
|
||||
|
||||
[[package]]
|
||||
name = "strength_reduce"
|
||||
version = "0.2.4"
|
||||
@@ -12803,6 +13259,17 @@ version = "2.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
||||
|
||||
[[package]]
|
||||
name = "super-seq-macro"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4a7568b180699c2138a4bfaadda9a33a7419251489e58760d3b4e74d6588da3d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"rhai",
|
||||
"syn 2.0.101",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "supports-color"
|
||||
version = "3.0.2"
|
||||
@@ -13087,6 +13554,12 @@ dependencies = [
|
||||
"unicode-width 0.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thin-vec"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "144f754d318415ac792f9d69fc87abbbfc043ce2ef041c60f16ad828f638717d"
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.69"
|
||||
@@ -13592,6 +14065,27 @@ version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3"
|
||||
|
||||
[[package]]
|
||||
name = "trace_and_split"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/matter-labs/zksync-airbender?tag=v0.5.0#a3c74040d2f994608f451550232392333400bbf1"
|
||||
dependencies = [
|
||||
"prover",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"setups",
|
||||
"worker",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "trace_holder"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/matter-labs/zksync-airbender?tag=v0.5.0#a3c74040d2f994608f451550232392333400bbf1"
|
||||
dependencies = [
|
||||
"field",
|
||||
"worker",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracer"
|
||||
version = "0.2.0"
|
||||
@@ -13600,7 +14094,7 @@ dependencies = [
|
||||
"clap",
|
||||
"common",
|
||||
"fnv",
|
||||
"object",
|
||||
"object 0.36.7",
|
||||
"tracing",
|
||||
"tracing-subscriber 0.3.19",
|
||||
]
|
||||
@@ -13743,6 +14237,16 @@ dependencies = [
|
||||
"syn 2.0.101",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "transcript"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/matter-labs/zksync-airbender?tag=v0.5.0#a3c74040d2f994608f451550232392333400bbf1"
|
||||
dependencies = [
|
||||
"blake2s_u32",
|
||||
"unroll",
|
||||
"worker",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "transpose"
|
||||
version = "0.2.3"
|
||||
@@ -13863,6 +14367,15 @@ dependencies = [
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "type-map"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb30dbbd9036155e74adad6812e9898d03ec374946234fbcebd5dfc7b9187b90"
|
||||
dependencies = [
|
||||
"rustc-hash 2.1.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typed-arena"
|
||||
version = "2.0.2"
|
||||
@@ -14107,6 +14620,36 @@ dependencies = [
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "verifier_common"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/matter-labs/zksync-airbender?tag=v0.5.0#a3c74040d2f994608f451550232392333400bbf1"
|
||||
dependencies = [
|
||||
"blake2s_u32",
|
||||
"cs",
|
||||
"field",
|
||||
"non_determinism_source",
|
||||
"poseidon2",
|
||||
"prover",
|
||||
"serde",
|
||||
"transcript",
|
||||
"unroll",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "verifier_generator"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/matter-labs/zksync-airbender?tag=v0.5.0#a3c74040d2f994608f451550232392333400bbf1"
|
||||
dependencies = [
|
||||
"proc-macro-error2",
|
||||
"proc-macro2",
|
||||
"prover",
|
||||
"quote",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"syn 2.0.101",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.5"
|
||||
@@ -14859,6 +15402,15 @@ dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "worker"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/matter-labs/zksync-airbender?tag=v0.5.0#a3c74040d2f994608f451550232392333400bbf1"
|
||||
dependencies = [
|
||||
"num_cpus",
|
||||
"rayon",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "writeable"
|
||||
version = "0.6.1"
|
||||
|
||||
@@ -3,6 +3,7 @@ members = [
|
||||
# zkVM interface
|
||||
"crates/zkvm-interface",
|
||||
# zkVMs
|
||||
"crates/zkvm/airbender",
|
||||
"crates/zkvm/jolt",
|
||||
"crates/zkvm/miden",
|
||||
"crates/zkvm/nexus",
|
||||
@@ -62,6 +63,9 @@ tracing-subscriber = "0.3.19"
|
||||
twirp = "0.9.1"
|
||||
twirp-build = "0.9.0"
|
||||
|
||||
# Airbender dependencies
|
||||
airbender_execution_utils = { git = "https://github.com/matter-labs/zksync-airbender", package = "execution_utils", tag = "v0.5.0" }
|
||||
|
||||
# Jolt dependencies
|
||||
ark-serialize = "0.5.0"
|
||||
common = { git = "https://github.com/a16z/jolt.git", rev = "55b9830a3944dde55d33a55c42522b81dd49f87a" }
|
||||
@@ -106,6 +110,7 @@ zkm-sdk = { git = "https://github.com/ProjectZKM/Ziren.git", tag = "v1.1.4" }
|
||||
# Local dependencies
|
||||
ere-zkvm-interface = { path = "crates/zkvm-interface" }
|
||||
|
||||
ere-airbender = { path = "crates/zkvm/airbender", default-features = false }
|
||||
ere-jolt = { path = "crates/zkvm/jolt", default-features = false }
|
||||
ere-miden = { path = "crates/zkvm/miden", default-features = false }
|
||||
ere-nexus = { path = "crates/zkvm/nexus", default-features = false }
|
||||
|
||||
@@ -13,6 +13,7 @@ serde.workspace = true
|
||||
tracing-subscriber = { workspace = true, features = ["env-filter"] }
|
||||
|
||||
# Local dependencies
|
||||
ere-airbender = { workspace = true, optional = true }
|
||||
ere-jolt = { workspace = true, optional = true }
|
||||
ere-miden = { workspace = true, optional = true }
|
||||
ere-nexus = { workspace = true, optional = true }
|
||||
@@ -30,6 +31,7 @@ ere-zkvm-interface.workspace = true
|
||||
default = []
|
||||
|
||||
# zkVM
|
||||
airbender = ["dep:ere-airbender"]
|
||||
jolt = ["dep:ere-jolt"]
|
||||
miden = ["dep:ere-miden"]
|
||||
nexus = ["dep:ere-nexus"]
|
||||
|
||||
@@ -8,7 +8,8 @@ use tracing_subscriber::EnvFilter;
|
||||
// Compile-time check to ensure exactly one zkVM feature is enabled for `ere-compiler`
|
||||
const _: () = {
|
||||
assert!(
|
||||
(cfg!(feature = "jolt") as u8
|
||||
(cfg!(feature = "airbender") as u8
|
||||
+ cfg!(feature = "jolt") as u8
|
||||
+ cfg!(feature = "miden") as u8
|
||||
+ cfg!(feature = "nexus") as u8
|
||||
+ cfg!(feature = "openvm") as u8
|
||||
@@ -50,6 +51,9 @@ fn main() -> Result<(), Error> {
|
||||
}
|
||||
|
||||
fn compile(guest_path: PathBuf) -> Result<impl Serialize, Error> {
|
||||
#[cfg(feature = "airbender")]
|
||||
let result = ere_airbender::compiler::RustRv32ima.compile(&guest_path);
|
||||
|
||||
#[cfg(feature = "jolt")]
|
||||
let result = if use_stock_rust() {
|
||||
ere_jolt::compiler::RustRv32ima.compile(&guest_path)
|
||||
|
||||
@@ -20,6 +20,7 @@ fn generate_crate_version() {
|
||||
|
||||
fn generate_zkvm_sdk_version_impl() {
|
||||
let [
|
||||
airbender_version,
|
||||
jolt_version,
|
||||
miden_version,
|
||||
nexus_version,
|
||||
@@ -29,6 +30,7 @@ fn generate_zkvm_sdk_version_impl() {
|
||||
sp1_version,
|
||||
ziren_version,
|
||||
] = [
|
||||
"execution_utils",
|
||||
"jolt-sdk",
|
||||
"miden-core",
|
||||
"nexus-sdk",
|
||||
@@ -51,6 +53,7 @@ fn generate_zkvm_sdk_version_impl() {
|
||||
r#"impl crate::ErezkVM {{
|
||||
pub fn sdk_version(&self) -> &'static str {{
|
||||
match self {{
|
||||
Self::Airbender => "{airbender_version}",
|
||||
Self::Jolt => "{jolt_version}",
|
||||
Self::Miden => "{miden_version}",
|
||||
Self::Nexus => "{nexus_version}",
|
||||
|
||||
@@ -95,6 +95,7 @@ const ERE_SERVER_PORT_OFFSET: u16 = 4174;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum ErezkVM {
|
||||
Airbender,
|
||||
Jolt,
|
||||
Miden,
|
||||
Nexus,
|
||||
@@ -109,6 +110,7 @@ pub enum ErezkVM {
|
||||
impl ErezkVM {
|
||||
pub fn as_str(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Airbender => "airbender",
|
||||
Self::Jolt => "jolt",
|
||||
Self::Miden => "miden",
|
||||
Self::Nexus => "nexus",
|
||||
@@ -126,7 +128,7 @@ impl ErezkVM {
|
||||
let suffix = match (gpu, self) {
|
||||
// Only the following zkVMs requires CUDA setup in the base image
|
||||
// when GPU support is required.
|
||||
(true, Self::OpenVM | Self::Risc0 | Self::Zisk) => "-cuda",
|
||||
(true, Self::Airbender | Self::OpenVM | Self::Risc0 | Self::Zisk) => "-cuda",
|
||||
_ => "",
|
||||
};
|
||||
format!("{version}{suffix}")
|
||||
@@ -195,7 +197,7 @@ impl ErezkVM {
|
||||
|
||||
let cuda_arch = cuda_arch();
|
||||
match self {
|
||||
ErezkVM::OpenVM | ErezkVM::Risc0 | ErezkVM::Zisk => {
|
||||
Self::Airbender | Self::OpenVM | Self::Risc0 | Self::Zisk => {
|
||||
if let Some(cuda_arch) = cuda_arch {
|
||||
cmd = cmd.build_arg("CUDA_ARCH", cuda_arch)
|
||||
}
|
||||
@@ -259,12 +261,12 @@ impl ErezkVM {
|
||||
|
||||
// zkVM specific options
|
||||
cmd = match self {
|
||||
ErezkVM::Risc0 => cmd
|
||||
Self::Risc0 => cmd
|
||||
.inherit_env("RISC0_SEGMENT_PO2")
|
||||
.inherit_env("RISC0_KECCAK_PO2"),
|
||||
// ZisK uses shared memory to exchange data between processes, it
|
||||
// requires at least 8G shared memory, here we set 16G for safety.
|
||||
ErezkVM::Zisk => cmd
|
||||
Self::Zisk => cmd
|
||||
.option("shm-size", "16G")
|
||||
.option("ulimit", "memlock=-1:-1")
|
||||
.inherit_env("ZISK_PORT")
|
||||
@@ -282,13 +284,14 @@ impl ErezkVM {
|
||||
// zkVM specific options when using GPU
|
||||
if gpu {
|
||||
cmd = match self {
|
||||
ErezkVM::OpenVM => cmd.gpus("all"),
|
||||
Self::Airbender => cmd.gpus("all"),
|
||||
Self::OpenVM => cmd.gpus("all"),
|
||||
// SP1 runs docker command to spin up the server to do GPU
|
||||
// proving, to give the client access to the prover service, we
|
||||
// need to use the host networking driver.
|
||||
ErezkVM::SP1 => cmd.mount_docker_socket().network("host"),
|
||||
ErezkVM::Risc0 => cmd.gpus("all").inherit_env("RISC0_DEFAULT_PROVER_NUM_GPUS"),
|
||||
ErezkVM::Zisk => cmd.gpus("all"),
|
||||
Self::SP1 => cmd.mount_docker_socket().network("host"),
|
||||
Self::Risc0 => cmd.gpus("all").inherit_env("RISC0_DEFAULT_PROVER_NUM_GPUS"),
|
||||
Self::Zisk => cmd.gpus("all"),
|
||||
_ => cmd,
|
||||
}
|
||||
}
|
||||
@@ -303,11 +306,11 @@ impl ErezkVM {
|
||||
// create a temporary directory and mount it on the top level, so
|
||||
// the volume could be shared, and override `TMPDIR` so we don't
|
||||
// need to mount the whole `/tmp`.
|
||||
ErezkVM::Risc0 => cmd
|
||||
Self::Risc0 => cmd
|
||||
.mount_docker_socket()
|
||||
.env("TMPDIR", tempdir.path().to_string_lossy())
|
||||
.volume(tempdir.path(), tempdir.path()),
|
||||
ErezkVM::SP1 => {
|
||||
Self::SP1 => {
|
||||
let groth16_circuit_path = home_dir().join(".sp1").join("circuits").join("groth16");
|
||||
cmd.mount_docker_socket()
|
||||
.env(
|
||||
@@ -336,6 +339,7 @@ impl FromStr for ErezkVM {
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
Ok(match s {
|
||||
"airbender" => Self::Airbender,
|
||||
"jolt" => Self::Jolt,
|
||||
"miden" => Self::Miden,
|
||||
"nexus" => Self::Nexus,
|
||||
@@ -610,6 +614,12 @@ mod test {
|
||||
};
|
||||
}
|
||||
|
||||
mod airbender {
|
||||
test_compile!(Airbender, "basic");
|
||||
test_execute!(Airbender, BasicProgramInput::valid().into_output_sha256());
|
||||
test_prove!(Airbender, BasicProgramInput::valid().into_output_sha256());
|
||||
}
|
||||
|
||||
mod jolt {
|
||||
test_compile!(Jolt, "basic");
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ tracing = { workspace = true, optional = true }
|
||||
tracing-subscriber = { workspace = true, features = ["env-filter"], optional = true }
|
||||
|
||||
# Local dependencies
|
||||
ere-airbender = { workspace = true, optional = true }
|
||||
ere-jolt = { workspace = true, optional = true }
|
||||
ere-miden = { workspace = true, optional = true }
|
||||
ere-nexus = { workspace = true, optional = true }
|
||||
@@ -45,6 +46,7 @@ default = []
|
||||
server = ["dep:clap", "dep:tower-http", "dep:tracing", "dep:tracing-subscriber", "tokio/macros", "tokio/rt-multi-thread", "tokio/signal"]
|
||||
|
||||
# zkVM
|
||||
airbender = ["dep:ere-airbender", "server"]
|
||||
jolt = ["dep:ere-jolt", "server"]
|
||||
miden = ["dep:ere-miden", "server"]
|
||||
nexus = ["dep:ere-nexus", "server"]
|
||||
|
||||
@@ -21,7 +21,8 @@ use twirp::{
|
||||
const _: () = {
|
||||
if cfg!(feature = "server") {
|
||||
assert!(
|
||||
(cfg!(feature = "jolt") as u8
|
||||
(cfg!(feature = "airbender") as u8
|
||||
+ cfg!(feature = "jolt") as u8
|
||||
+ cfg!(feature = "miden") as u8
|
||||
+ cfg!(feature = "nexus") as u8
|
||||
+ cfg!(feature = "openvm") as u8
|
||||
@@ -111,6 +112,9 @@ fn construct_zkvm(program: Vec<u8>, resource: ProverResourceType) -> Result<impl
|
||||
let (program, _) = bincode::serde::decode_from_slice(&program, bincode::config::legacy())
|
||||
.with_context(|| "Failed to deserialize program")?;
|
||||
|
||||
#[cfg(feature = "airbender")]
|
||||
let zkvm = Ok::<_, Error>(ere_airbender::EreAirbender::new(program, resource));
|
||||
|
||||
#[cfg(feature = "jolt")]
|
||||
let zkvm = ere_jolt::EreJolt::new(program, resource);
|
||||
|
||||
|
||||
28
crates/zkvm/airbender/Cargo.toml
Normal file
28
crates/zkvm/airbender/Cargo.toml
Normal file
@@ -0,0 +1,28 @@
|
||||
[package]
|
||||
name = "ere-airbender"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
bincode = { workspace = true, features = ["alloc", "serde"] }
|
||||
serde_json.workspace = true
|
||||
tempfile.workspace = true
|
||||
thiserror.workspace = true
|
||||
|
||||
# Airbender dependencies
|
||||
airbender_execution_utils.workspace = true
|
||||
|
||||
# Local dependencies
|
||||
ere-compile-utils.workspace = true
|
||||
ere-zkvm-interface.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
ere-test-utils = { workspace = true, features = ["host"] }
|
||||
|
||||
[build-dependencies]
|
||||
ere-build-utils.workspace = true
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
5
crates/zkvm/airbender/build.rs
Normal file
5
crates/zkvm/airbender/build.rs
Normal file
@@ -0,0 +1,5 @@
|
||||
use ere_build_utils::detect_and_generate_name_and_sdk_version;
|
||||
|
||||
fn main() {
|
||||
detect_and_generate_name_and_sdk_version("airbender", "execution_utils");
|
||||
}
|
||||
244
crates/zkvm/airbender/src/client.rs
Normal file
244
crates/zkvm/airbender/src/client.rs
Normal file
@@ -0,0 +1,244 @@
|
||||
use crate::error::AirbenderError;
|
||||
use airbender_execution_utils::{
|
||||
Machine, ProgramProof, compute_chain_encoding, generate_params_for_binary,
|
||||
universal_circuit_verifier_vk, verify_recursion_log_23_layer,
|
||||
};
|
||||
use ere_zkvm_interface::PublicValues;
|
||||
use std::{array, fs, io::BufRead, iter, process::Command};
|
||||
use tempfile::tempdir;
|
||||
|
||||
/// Verification key hash chain.
|
||||
///
|
||||
/// For recursive verifier program, it exposes the chaining hash of verification
|
||||
/// keys of programs that it verifies, which is computed as
|
||||
/// `blake(blake(blake(0 || base_vk)|| verifier_0_vk) || verifier_1_vk)...`.
|
||||
///
|
||||
/// For a base program, the VK is computed as `blake(PC || setup_caps)`, where
|
||||
/// `PC` is the program counter value at the end of execution, and `setup_caps`
|
||||
/// is the merkle tree caps derived from the program.
|
||||
pub type VkHashChain = [u32; 8];
|
||||
|
||||
pub struct AirbenderSdk {
|
||||
bin: Vec<u8>,
|
||||
vk_hash_chain: VkHashChain,
|
||||
gpu: bool,
|
||||
}
|
||||
|
||||
impl AirbenderSdk {
|
||||
pub fn new(bin: &[u8], gpu: bool) -> Self {
|
||||
let vk_hash_chain = {
|
||||
// Compute base VK as `blake(PC || setup_caps)`.
|
||||
let base_vk = generate_params_for_binary(bin, Machine::Standard);
|
||||
// The 1st recursion layer VK
|
||||
let verifier_vk = universal_circuit_verifier_vk().params;
|
||||
// Compute hash chain as `blake(blake(0 || guest_vk) || verifier_vk)`,
|
||||
// that is expected to be exposed by second layer recursion program.
|
||||
compute_chain_encoding(vec![[0; 8], base_vk, verifier_vk])
|
||||
};
|
||||
Self {
|
||||
bin: bin.to_vec(),
|
||||
vk_hash_chain,
|
||||
gpu,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn execute(&self, input: &[u8]) -> Result<(PublicValues, u64), AirbenderError> {
|
||||
let tempdir = tempdir().map_err(AirbenderError::TempDir)?;
|
||||
|
||||
let bin_path = tempdir.path().join("guest.bin");
|
||||
fs::write(&bin_path, &self.bin)
|
||||
.map_err(|err| AirbenderError::write_file(err, "guest.bin", &bin_path))?;
|
||||
|
||||
let input_path = tempdir.path().join("input.hex");
|
||||
fs::write(&input_path, encode_input(input))
|
||||
.map_err(|err| AirbenderError::write_file(err, "input.hex", &input_path))?;
|
||||
|
||||
let output = Command::new("airbender-cli")
|
||||
.arg("run")
|
||||
.arg("--bin")
|
||||
.arg(&bin_path)
|
||||
.arg("--input-file")
|
||||
.arg(&input_path)
|
||||
.args(["--cycles", &u64::MAX.to_string()])
|
||||
.output()
|
||||
.map_err(AirbenderError::AirbenderRun)?;
|
||||
|
||||
if !output.status.success() {
|
||||
return Err(AirbenderError::AirbenderRunFailed {
|
||||
status: output.status,
|
||||
});
|
||||
}
|
||||
|
||||
// Parse public values 8 u32 words (32 bytes) from stdout in format of:
|
||||
// `Result: {v0}, {v1}, {v2}, {v3}, {v4}, {v5}, {v6}, {v7}`
|
||||
let public_values = output
|
||||
.stdout
|
||||
.lines()
|
||||
.find_map(|line| {
|
||||
let line = line.ok()?;
|
||||
let line = line.split_once("Result:")?.1;
|
||||
let mut words = line.split(',');
|
||||
let mut bytes = Vec::with_capacity(32);
|
||||
for _ in 0..8 {
|
||||
bytes.extend(words.next()?.trim().parse::<u32>().ok()?.to_le_bytes())
|
||||
}
|
||||
Some(bytes)
|
||||
})
|
||||
.ok_or_else(|| {
|
||||
AirbenderError::ParsePublicValue(
|
||||
String::from_utf8_lossy(&output.stdout).to_string(),
|
||||
)
|
||||
})?;
|
||||
|
||||
// Parse cycles from stdout in format of:
|
||||
// `Took {cycles} cycles to finish`
|
||||
let cycles = output
|
||||
.stdout
|
||||
.lines()
|
||||
.find_map(|line| {
|
||||
let line = line.ok()?;
|
||||
let line = line.split_once("Took ")?.1;
|
||||
let cycle = line.split_once(" cycles")?.0;
|
||||
cycle.parse().ok()
|
||||
})
|
||||
.ok_or_else(|| {
|
||||
AirbenderError::ParseCycles(String::from_utf8_lossy(&output.stdout).to_string())
|
||||
})?;
|
||||
|
||||
Ok((public_values, cycles))
|
||||
}
|
||||
|
||||
pub fn prove(&self, input: &[u8]) -> Result<(PublicValues, ProgramProof), AirbenderError> {
|
||||
let tempdir = tempdir().map_err(AirbenderError::TempDir)?;
|
||||
|
||||
let bin_path = tempdir.path().join("guest.bin");
|
||||
fs::write(&bin_path, &self.bin)
|
||||
.map_err(|err| AirbenderError::write_file(err, "guest.bin", &bin_path))?;
|
||||
|
||||
let input_path = tempdir.path().join("input.hex");
|
||||
fs::write(&input_path, encode_input(input))
|
||||
.map_err(|err| AirbenderError::write_file(err, "input.hex", &input_path))?;
|
||||
|
||||
let output_dir = tempdir.path().join("output");
|
||||
fs::create_dir_all(&output_dir)
|
||||
.map_err(|err| AirbenderError::create_dir(err, "output", &output_dir))?;
|
||||
|
||||
// Prove guest program + 1st recursion layer (tree of recursive proofs until root).
|
||||
let output = Command::new("airbender-cli")
|
||||
.arg("prove")
|
||||
.arg("--bin")
|
||||
.arg(&bin_path)
|
||||
.arg("--output-dir")
|
||||
.arg(&output_dir)
|
||||
.arg("--input-file")
|
||||
.arg(&input_path)
|
||||
.args(["--until", "final-recursion"])
|
||||
.args(["--cycles", &u64::MAX.to_string()])
|
||||
.args(self.gpu.then_some("--gpu"))
|
||||
.output()
|
||||
.map_err(AirbenderError::AirbenderProve)?;
|
||||
|
||||
if !output.status.success() {
|
||||
return Err(AirbenderError::AirbenderProveFailed {
|
||||
status: output.status,
|
||||
stderr: String::from_utf8_lossy(&output.stderr).into_owned(),
|
||||
});
|
||||
}
|
||||
|
||||
let proof_path = output_dir.join("recursion_program_proof.json");
|
||||
if !proof_path.exists() {
|
||||
return Err(AirbenderError::RecursionProofNotFound { path: proof_path });
|
||||
}
|
||||
|
||||
// Prove 2nd recursion layer (wrapping root of 1st recursion layer)
|
||||
let output = Command::new("airbender-cli")
|
||||
.arg("prove-final")
|
||||
.arg("--input-file")
|
||||
.arg(&proof_path)
|
||||
.arg("--output-dir")
|
||||
.arg(&output_dir)
|
||||
.args(self.gpu.then_some("--gpu"))
|
||||
.output()
|
||||
.map_err(AirbenderError::AirbenderProveFinal)?;
|
||||
|
||||
if !output.status.success() {
|
||||
return Err(AirbenderError::AirbenderProveFinalFailed {
|
||||
status: output.status,
|
||||
stderr: String::from_utf8_lossy(&output.stderr).into_owned(),
|
||||
});
|
||||
}
|
||||
|
||||
let proof_path = output_dir.join("final_program_proof.json");
|
||||
if !proof_path.exists() {
|
||||
return Err(AirbenderError::FinalProofNotFound { path: proof_path });
|
||||
}
|
||||
|
||||
let proof_bytes = fs::read(&proof_path).map_err(|err| {
|
||||
AirbenderError::read_file(err, "final_program_proof.json", &proof_path)
|
||||
})?;
|
||||
|
||||
let proof: ProgramProof =
|
||||
serde_json::from_slice(&proof_bytes).map_err(AirbenderError::JsonDeserialize)?;
|
||||
|
||||
let (public_values, vk_hash_chain) = extract_public_values_and_vk_hash_chain(&proof)?;
|
||||
|
||||
if self.vk_hash_chain != vk_hash_chain {
|
||||
return Err(AirbenderError::UnexpectedVkHashChain {
|
||||
preprocessed: self.vk_hash_chain,
|
||||
proved: vk_hash_chain,
|
||||
});
|
||||
}
|
||||
|
||||
Ok((public_values, proof))
|
||||
}
|
||||
|
||||
pub fn verify(&self, proof: &ProgramProof) -> Result<PublicValues, AirbenderError> {
|
||||
let is_valid = verify_recursion_log_23_layer(proof);
|
||||
if !is_valid {
|
||||
return Err(AirbenderError::ProofVerificationFailed);
|
||||
}
|
||||
|
||||
let (public_values, vk_hash_chain) = extract_public_values_and_vk_hash_chain(proof)?;
|
||||
|
||||
if self.vk_hash_chain != vk_hash_chain {
|
||||
return Err(AirbenderError::UnexpectedVkHashChain {
|
||||
preprocessed: self.vk_hash_chain,
|
||||
proved: vk_hash_chain,
|
||||
});
|
||||
}
|
||||
|
||||
Ok(public_values)
|
||||
}
|
||||
}
|
||||
|
||||
/// Encode input with length prefixed to hex string for `airbender-cli`.
|
||||
fn encode_input(input: &[u8]) -> String {
|
||||
iter::once((input.len() as u32).to_le_bytes().as_slice())
|
||||
.chain(input.chunks(4))
|
||||
.map(|chunk| {
|
||||
let mut bytes = [0u8; 4];
|
||||
bytes[..chunk.len()].copy_from_slice(chunk);
|
||||
format!("{:08x}", u32::from_le_bytes(bytes))
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
// Extract public values and VK hash chain from register values.
|
||||
fn extract_public_values_and_vk_hash_chain(
|
||||
proof: &ProgramProof,
|
||||
) -> Result<(PublicValues, VkHashChain), AirbenderError> {
|
||||
if proof.register_final_values.len() != 32 {
|
||||
return Err(AirbenderError::InvalidRegisterCount(
|
||||
proof.register_final_values.len(),
|
||||
));
|
||||
}
|
||||
|
||||
let public_values = proof.register_final_values[10..18]
|
||||
.iter()
|
||||
.flat_map(|value| value.value.to_le_bytes())
|
||||
.collect();
|
||||
|
||||
let vk_chain_hash = array::from_fn(|i| proof.register_final_values[18 + i].value);
|
||||
|
||||
Ok((public_values, vk_chain_hash))
|
||||
}
|
||||
5
crates/zkvm/airbender/src/compiler.rs
Normal file
5
crates/zkvm/airbender/src/compiler.rs
Normal file
@@ -0,0 +1,5 @@
|
||||
mod rust_rv32ima;
|
||||
|
||||
pub use rust_rv32ima::RustRv32ima;
|
||||
|
||||
pub type AirbenderProgram = Vec<u8>;
|
||||
97
crates/zkvm/airbender/src/compiler/rust_rv32ima.rs
Normal file
97
crates/zkvm/airbender/src/compiler/rust_rv32ima.rs
Normal file
@@ -0,0 +1,97 @@
|
||||
use crate::{compiler::AirbenderProgram, error::AirbenderError};
|
||||
use ere_compile_utils::CargoBuildCmd;
|
||||
use ere_zkvm_interface::Compiler;
|
||||
use std::{
|
||||
env,
|
||||
io::Write,
|
||||
path::Path,
|
||||
process::{Command, Stdio},
|
||||
};
|
||||
|
||||
const TARGET_TRIPLE: &str = "riscv32ima-unknown-none-elf";
|
||||
// Rust flags according to https://github.com/matter-labs/zksync-airbender/blob/v0.5.0/examples/dynamic_fibonacci/.cargo/config.toml.
|
||||
const RUSTFLAGS: &[&str] = &[
|
||||
// Replace atomic ops with nonatomic versions since the guest is single threaded.
|
||||
"-C",
|
||||
"passes=lower-atomic",
|
||||
"-C",
|
||||
"target-feature=-unaligned-scalar-mem,+relax",
|
||||
"-C",
|
||||
"link-arg=--save-temps",
|
||||
"-C",
|
||||
"force-frame-pointers",
|
||||
];
|
||||
const CARGO_BUILD_OPTIONS: &[&str] = &[
|
||||
// For bare metal we have to build core and alloc
|
||||
"-Zbuild-std=core,alloc",
|
||||
];
|
||||
|
||||
const LINKER_SCRIPT: &str = concat!(
|
||||
include_str!("rust_rv32ima/memory.x"),
|
||||
include_str!("rust_rv32ima/link.x"),
|
||||
);
|
||||
|
||||
/// Compiler for Rust guest program to RV32IMA architecture.
|
||||
pub struct RustRv32ima;
|
||||
|
||||
impl Compiler for RustRv32ima {
|
||||
type Error = AirbenderError;
|
||||
|
||||
type Program = AirbenderProgram;
|
||||
|
||||
fn compile(&self, guest_directory: &Path) -> Result<Self::Program, Self::Error> {
|
||||
let toolchain = env::var("ERE_RUST_TOOLCHAIN").unwrap_or_else(|_| "nightly".into());
|
||||
let elf = CargoBuildCmd::new()
|
||||
.linker_script(Some(LINKER_SCRIPT))
|
||||
.toolchain(toolchain)
|
||||
.build_options(CARGO_BUILD_OPTIONS)
|
||||
.rustflags(RUSTFLAGS)
|
||||
.exec(guest_directory, TARGET_TRIPLE)?;
|
||||
let bin = objcopy_binary(&elf)?;
|
||||
Ok(bin)
|
||||
}
|
||||
}
|
||||
|
||||
fn objcopy_binary(elf: &[u8]) -> Result<Vec<u8>, AirbenderError> {
|
||||
let mut child = Command::new("rust-objcopy")
|
||||
.args(["-O", "binary", "-", "-"])
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped())
|
||||
.spawn()
|
||||
.map_err(AirbenderError::RustObjcopy)?;
|
||||
|
||||
child
|
||||
.stdin
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.write_all(elf)
|
||||
.map_err(AirbenderError::RustObjcopyStdin)?;
|
||||
|
||||
let output = child
|
||||
.wait_with_output()
|
||||
.map_err(AirbenderError::RustObjcopy)?;
|
||||
|
||||
if !output.status.success() {
|
||||
return Err(AirbenderError::RustObjcopyFailed {
|
||||
status: output.status,
|
||||
stderr: String::from_utf8_lossy(&output.stderr).into_owned(),
|
||||
});
|
||||
}
|
||||
|
||||
Ok(output.stdout)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::compiler::RustRv32ima;
|
||||
use ere_test_utils::host::testing_guest_directory;
|
||||
use ere_zkvm_interface::Compiler;
|
||||
|
||||
#[test]
|
||||
fn test_compile() {
|
||||
let guest_directory = testing_guest_directory("airbender", "basic");
|
||||
let bin = RustRv32ima.compile(&guest_directory).unwrap();
|
||||
assert!(!bin.is_empty(), "Binary should not be empty.");
|
||||
}
|
||||
}
|
||||
193
crates/zkvm/airbender/src/compiler/rust_rv32ima/link.x
Normal file
193
crates/zkvm/airbender/src/compiler/rust_rv32ima/link.x
Normal file
@@ -0,0 +1,193 @@
|
||||
/* Copied from https://github.com/matter-labs/zksync-airbender/blob/v0.5.0/examples/scripts/lds/link.x */
|
||||
|
||||
PROVIDE(_stext = ORIGIN(REGION_TEXT));
|
||||
PROVIDE(_max_hart_id = 0);
|
||||
PROVIDE(_hart_stack_size = 64M);
|
||||
PROVIDE(_heap_size = 768M);
|
||||
|
||||
/*
|
||||
PROVIDE(UserSoft = DefaultHandler);
|
||||
PROVIDE(SupervisorSoft = DefaultHandler);
|
||||
PROVIDE(MachineSoft = DefaultHandler);
|
||||
PROVIDE(UserTimer = DefaultHandler);
|
||||
PROVIDE(SupervisorTimer = DefaultHandler);
|
||||
PROVIDE(MachineTimer = DefaultHandler);
|
||||
PROVIDE(UserExternal = DefaultHandler);
|
||||
PROVIDE(SupervisorExternal = DefaultHandler);
|
||||
PROVIDE(MachineExternal = DefaultHandler);
|
||||
|
||||
PROVIDE(DefaultHandler = DefaultInterruptHandler);
|
||||
PROVIDE(ExceptionHandler = DefaultExceptionHandler);
|
||||
*/
|
||||
|
||||
/* # Pre-initialization function */
|
||||
/* If the user overrides this using the `#[pre_init]` attribute or by creating a `__pre_init` function,
|
||||
then the function this points to will be called before the RAM is initialized. */
|
||||
PROVIDE(__pre_init = default_pre_init);
|
||||
|
||||
/* A PAC/HAL defined routine that should initialize custom interrupt controller if needed. */
|
||||
/*
|
||||
PROVIDE(_setup_interrupts = default_setup_interrupts);
|
||||
*/
|
||||
|
||||
|
||||
/* # Start trap function override
|
||||
By default uses the riscv crates default trap handler
|
||||
but by providing the `_start_trap` symbol external crates can override.
|
||||
*/
|
||||
PROVIDE(_start_trap = default_start_trap);
|
||||
PROVIDE(_machine_start_trap = machine_default_start_trap);
|
||||
|
||||
PHDRS
|
||||
{
|
||||
text PT_LOAD;
|
||||
data PT_LOAD;
|
||||
bss PT_LOAD;
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text.dummy (NOLOAD) :
|
||||
{
|
||||
/* This section is intended to make _stext address work */
|
||||
. = ABSOLUTE(_stext);
|
||||
} > REGION_TEXT AT > REGION_TEXT :text
|
||||
|
||||
.text _stext : ALIGN(4096)
|
||||
{
|
||||
/* Put reset handler first in .text section so it ends up as the entry */
|
||||
/* point of the program. */
|
||||
KEEP(*(.init));
|
||||
KEEP(*(.init.rust));
|
||||
. = ALIGN(4);
|
||||
*(.trap);
|
||||
*(.trap.rust);
|
||||
|
||||
*(.text .text.*);
|
||||
} > REGION_TEXT AT > REGION_TEXT :text
|
||||
|
||||
.rodata : ALIGN(4)
|
||||
{
|
||||
*(.srodata .srodata.*);
|
||||
*(.rodata .rodata.*);
|
||||
|
||||
/* 4-byte align the end (VMA) of this section.
|
||||
This is required by LLD to ensure the LMA of the following
|
||||
section will have the correct alignment. */
|
||||
. = ALIGN(4);
|
||||
} > REGION_RODATA AT > REGION_RODATA :text
|
||||
|
||||
/* fictitious region that represents the memory available for the stack */
|
||||
.stack ORIGIN(REGION_STACK) (NOLOAD) : ALIGN(4096)
|
||||
{
|
||||
_estack = .;
|
||||
. += (_max_hart_id + 1) * _hart_stack_size;
|
||||
. = ALIGN(4);
|
||||
_sstack = .;
|
||||
} > REGION_STACK
|
||||
|
||||
.data : ALIGN(4096)
|
||||
{
|
||||
_sidata = LOADADDR(.data);
|
||||
_sdata = .;
|
||||
/* Must be called __global_pointer$ for linker relaxations to work. */
|
||||
PROVIDE(__global_pointer$ = . + 0x800);
|
||||
*(.sdata .sdata.* .sdata2 .sdata2.*);
|
||||
*(.data .data.*);
|
||||
. = ALIGN(4);
|
||||
_edata = .;
|
||||
} > REGION_DATA AT > REGION_DATAINIT :data
|
||||
|
||||
.bss (NOLOAD) : ALIGN(4096)
|
||||
{
|
||||
_sbss = .;
|
||||
*(.sbss .sbss.* .bss .bss.*);
|
||||
. = ALIGN(4);
|
||||
_ebss = .;
|
||||
} > REGION_BSS AT > REGION_BSS :bss
|
||||
|
||||
/* fictitious region that represents the memory available for the heap */
|
||||
.heap (NOLOAD) : ALIGN(2097152)
|
||||
{
|
||||
_sheap = .;
|
||||
. += _heap_size;
|
||||
. = ALIGN(2097152);
|
||||
_eheap = .;
|
||||
} > REGION_HEAP
|
||||
|
||||
/* fake output .got section */
|
||||
/* Dynamic relocations are unsupported. This section is only used to detect
|
||||
relocatable code in the input files and raise an error if relocatable code
|
||||
is found */
|
||||
.got (INFO) :
|
||||
{
|
||||
KEEP(*(.got .got.*));
|
||||
}
|
||||
|
||||
.eh_frame (INFO) : { KEEP(*(.eh_frame)) }
|
||||
.eh_frame_hdr (INFO) : { *(.eh_frame_hdr) }
|
||||
}
|
||||
|
||||
/* Do not exceed this mark in the error messages above | */
|
||||
ASSERT(ORIGIN(REGION_TEXT) % 4 == 0, "
|
||||
ERROR(riscv-rt): the start of the REGION_TEXT must be 4-byte aligned");
|
||||
|
||||
ASSERT(ORIGIN(REGION_RODATA) % 4 == 0, "
|
||||
ERROR(riscv-rt): the start of the REGION_RODATA must be 4-byte aligned");
|
||||
|
||||
ASSERT(ORIGIN(REGION_DATAINIT) % 4 == 0, "
|
||||
ERROR(riscv-rt): the start of the REGION_DATAINIT must be 4-byte aligned");
|
||||
|
||||
ASSERT(ORIGIN(REGION_DATA) % 4 == 0, "
|
||||
ERROR(riscv-rt): the start of the REGION_DATA must be 4-byte aligned");
|
||||
|
||||
ASSERT(ORIGIN(REGION_HEAP) % 4 == 0, "
|
||||
ERROR(riscv-rt): the start of the REGION_HEAP must be 4-byte aligned");
|
||||
|
||||
ASSERT(ORIGIN(REGION_TEXT) % 4 == 0, "
|
||||
ERROR(riscv-rt): the start of the REGION_TEXT must be 4-byte aligned");
|
||||
|
||||
ASSERT(ORIGIN(REGION_STACK) % 4 == 0, "
|
||||
ERROR(riscv-rt): the start of the REGION_STACK must be 4-byte aligned");
|
||||
|
||||
ASSERT(_stext % 4 == 0, "
|
||||
ERROR(riscv-rt): `_stext` must be 4-byte aligned");
|
||||
|
||||
ASSERT(_sdata % 4 == 0 && _edata % 4 == 0, "
|
||||
BUG(riscv-rt): .data is not 4-byte aligned");
|
||||
|
||||
ASSERT(_sidata % 4 == 0, "
|
||||
BUG(riscv-rt): the LMA of .data is not 4-byte aligned");
|
||||
|
||||
ASSERT(_sbss % 4 == 0 && _ebss % 4 == 0, "
|
||||
BUG(riscv-rt): .bss is not 4-byte aligned");
|
||||
|
||||
ASSERT(_sheap % 4 == 0, "
|
||||
BUG(riscv-rt): start of .heap is not 4-byte aligned");
|
||||
|
||||
ASSERT(_stext + SIZEOF(.text) < ORIGIN(REGION_TEXT) + LENGTH(REGION_TEXT), "
|
||||
ERROR(riscv-rt): The .text section must be placed inside the REGION_TEXT region.
|
||||
Set _stext to an address smaller than 'ORIGIN(REGION_TEXT) + LENGTH(REGION_TEXT)'");
|
||||
|
||||
ASSERT(_sidata + SIZEOF(.data) < ORIGIN(REGION_DATAINIT) + LENGTH(REGION_DATAINIT), "
|
||||
ERROR(riscv-rt): The init data for .data section must be placed inside the REGION_DATAINIT region.
|
||||
Set _sidata to an address smaller than 'ORIGIN(REGION_DATAINIT) + LENGTH(REGION_DATAINIT)'");
|
||||
|
||||
ASSERT(SIZEOF(.stack) >= (_max_hart_id + 1) * _hart_stack_size, "
|
||||
ERROR(riscv-rt): .stack section is too small for allocating stacks for all the harts.
|
||||
Consider changing `_max_hart_id` or `_hart_stack_size`.");
|
||||
|
||||
ASSERT(SIZEOF(.got) == 0, "
|
||||
.got section detected in the input files. Dynamic relocations are not
|
||||
supported. If you are linking to C code compiled using the `gcc` crate
|
||||
then modify your build script to compile the C code _without_ the
|
||||
-fPIC flag. See the documentation of the `gcc::Config.fpic` method for
|
||||
details.");
|
||||
|
||||
ASSERT(SIZEOF(.data) == 0, "
|
||||
.data section detected in the input files. Global variables with non-trivial
|
||||
initialization are not supported yet. Variables with zero-initialization can be
|
||||
linked to .bss section instead, as the platform guarantees zero-initialization
|
||||
of all RAM space.");
|
||||
|
||||
/* Do not exceed this mark in the error messages above | */
|
||||
15
crates/zkvm/airbender/src/compiler/rust_rv32ima/memory.x
Normal file
15
crates/zkvm/airbender/src/compiler/rust_rv32ima/memory.x
Normal file
@@ -0,0 +1,15 @@
|
||||
/* Copied from https://github.com/matter-labs/zksync-airbender/blob/v0.5.0/examples/scripts/lds/memory.x */
|
||||
|
||||
MEMORY
|
||||
{
|
||||
ROM (rx): ORIGIN = 0, LENGTH = 2M
|
||||
RAM (rwa!x) : ORIGIN = 2M, LENGTH = 1022M
|
||||
}
|
||||
|
||||
REGION_ALIAS("REGION_TEXT", ROM);
|
||||
REGION_ALIAS("REGION_RODATA", ROM);
|
||||
REGION_ALIAS("REGION_DATAINIT", ROM);
|
||||
REGION_ALIAS("REGION_STACK", RAM);
|
||||
REGION_ALIAS("REGION_DATA", RAM);
|
||||
REGION_ALIAS("REGION_BSS", RAM);
|
||||
REGION_ALIAS("REGION_HEAP", RAM);
|
||||
99
crates/zkvm/airbender/src/error.rs
Normal file
99
crates/zkvm/airbender/src/error.rs
Normal file
@@ -0,0 +1,99 @@
|
||||
use crate::client::VkHashChain;
|
||||
use ere_zkvm_interface::zkVMError;
|
||||
use std::{
|
||||
io,
|
||||
path::{Path, PathBuf},
|
||||
process::ExitStatus,
|
||||
};
|
||||
use thiserror::Error;
|
||||
|
||||
impl From<AirbenderError> for zkVMError {
|
||||
fn from(value: AirbenderError) -> Self {
|
||||
zkVMError::Other(Box::new(value))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum AirbenderError {
|
||||
// Compilation
|
||||
#[error(transparent)]
|
||||
CompileError(#[from] ere_compile_utils::CompileError),
|
||||
#[error("Failed to execute `rust-objcopy`: {0}")]
|
||||
RustObjcopy(#[source] io::Error),
|
||||
#[error("`rust-objcopy` failed with status: {status}\nstderr: {stderr}")]
|
||||
RustObjcopyFailed { status: ExitStatus, stderr: String },
|
||||
#[error("Failed to write ELF to `rust-objcopy` stdin: {0}")]
|
||||
RustObjcopyStdin(#[source] io::Error),
|
||||
|
||||
// IO and file system
|
||||
#[error("IO failure: {0}")]
|
||||
Io(#[from] io::Error),
|
||||
#[error("IO failure in temporary directory: {0}")]
|
||||
TempDir(io::Error),
|
||||
|
||||
// Serialization
|
||||
#[error("Bincode encode failed: {0}")]
|
||||
BincodeEncode(#[from] bincode::error::EncodeError),
|
||||
#[error("Bincode decode failed: {0}")]
|
||||
BincodeDecode(#[from] bincode::error::DecodeError),
|
||||
#[error("JSON deserialization failed: {0}")]
|
||||
JsonDeserialize(#[from] serde_json::Error),
|
||||
|
||||
// Execution
|
||||
#[error("Failed to execute `airbender-cli run`: {0}")]
|
||||
AirbenderRun(#[source] io::Error),
|
||||
#[error("`airbender-cli run` failed with status: {status}")]
|
||||
AirbenderRunFailed { status: ExitStatus },
|
||||
#[error("Failed to parse public value from stdout: {0}")]
|
||||
ParsePublicValue(String),
|
||||
#[error("Failed to parse cycles from stdout: {0}")]
|
||||
ParseCycles(String),
|
||||
|
||||
// Proving
|
||||
#[error("Failed to execute `airbender-cli prove`: {0}")]
|
||||
AirbenderProve(#[source] io::Error),
|
||||
#[error("`airbender-cli prove` failed with status: {status}\nstderr: {stderr}")]
|
||||
AirbenderProveFailed { status: ExitStatus, stderr: String },
|
||||
#[error("Failed to execute `airbender-cli prove-final`: {0}")]
|
||||
AirbenderProveFinal(#[source] io::Error),
|
||||
#[error("`airbender-cli prove-final` failed with status: {status}\nstderr: {stderr}")]
|
||||
AirbenderProveFinalFailed { status: ExitStatus, stderr: String },
|
||||
#[error("Recursion proof not found at {path}")]
|
||||
RecursionProofNotFound { path: PathBuf },
|
||||
#[error("Final proof not found at {path}")]
|
||||
FinalProofNotFound { path: PathBuf },
|
||||
|
||||
// Verification
|
||||
#[error("Proof verification failed")]
|
||||
ProofVerificationFailed,
|
||||
#[error("Invalid final register count, expected 32 but got {0}")]
|
||||
InvalidRegisterCount(usize),
|
||||
#[error(
|
||||
"Unexpected verification key hash chain - preprocessed: {preprocessed:?}, proved: {proved:?}"
|
||||
)]
|
||||
UnexpectedVkHashChain {
|
||||
preprocessed: VkHashChain,
|
||||
proved: VkHashChain,
|
||||
},
|
||||
}
|
||||
|
||||
impl AirbenderError {
|
||||
pub fn io(err: io::Error, context: impl Into<String>) -> Self {
|
||||
Self::Io(io::Error::other(format!("{}: {}", context.into(), err)))
|
||||
}
|
||||
|
||||
pub fn create_dir(err: io::Error, id: &str, path: impl AsRef<Path>) -> Self {
|
||||
let ctx = format!("Failed to create dir {id} at {}", path.as_ref().display());
|
||||
Self::io(err, ctx)
|
||||
}
|
||||
|
||||
pub fn write_file(err: io::Error, id: &str, path: impl AsRef<Path>) -> Self {
|
||||
let ctx = format!("Failed to write {id} to {}", path.as_ref().display());
|
||||
Self::io(err, ctx)
|
||||
}
|
||||
|
||||
pub fn read_file(err: io::Error, id: &str, path: impl AsRef<Path>) -> Self {
|
||||
let ctx = format!("Failed to read {id} from {}", path.as_ref().display());
|
||||
Self::io(err, ctx)
|
||||
}
|
||||
}
|
||||
153
crates/zkvm/airbender/src/lib.rs
Normal file
153
crates/zkvm/airbender/src/lib.rs
Normal file
@@ -0,0 +1,153 @@
|
||||
#![cfg_attr(not(test), warn(unused_crate_dependencies))]
|
||||
|
||||
use crate::{client::AirbenderSdk, compiler::AirbenderProgram, error::AirbenderError};
|
||||
use airbender_execution_utils::ProgramProof;
|
||||
use ere_zkvm_interface::{
|
||||
ProgramExecutionReport, ProgramProvingReport, Proof, ProofKind, ProverResourceType,
|
||||
PublicValues, zkVM, zkVMError,
|
||||
};
|
||||
use std::time::Instant;
|
||||
|
||||
mod client;
|
||||
pub mod compiler;
|
||||
pub mod error;
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/name_and_sdk_version.rs"));
|
||||
|
||||
pub struct EreAirbender {
|
||||
sdk: AirbenderSdk,
|
||||
}
|
||||
|
||||
impl EreAirbender {
|
||||
pub fn new(bin: AirbenderProgram, resource: ProverResourceType) -> Self {
|
||||
let gpu = matches!(resource, ProverResourceType::Gpu);
|
||||
let sdk = AirbenderSdk::new(&bin, gpu);
|
||||
Self { sdk }
|
||||
}
|
||||
}
|
||||
|
||||
impl zkVM for EreAirbender {
|
||||
fn execute(&self, input: &[u8]) -> Result<(PublicValues, ProgramExecutionReport), zkVMError> {
|
||||
let start = Instant::now();
|
||||
let (public_values, cycles) = self.sdk.execute(input)?;
|
||||
let execution_duration = start.elapsed();
|
||||
|
||||
Ok((
|
||||
public_values,
|
||||
ProgramExecutionReport {
|
||||
total_num_cycles: cycles,
|
||||
execution_duration,
|
||||
..Default::default()
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
fn prove(
|
||||
&self,
|
||||
input: &[u8],
|
||||
proof_kind: ProofKind,
|
||||
) -> Result<(PublicValues, Proof, ProgramProvingReport), zkVMError> {
|
||||
if proof_kind != ProofKind::Compressed {
|
||||
panic!("Only Compressed proof kind is supported.");
|
||||
}
|
||||
|
||||
let start = Instant::now();
|
||||
let (public_values, proof) = self.sdk.prove(input)?;
|
||||
let proving_time = start.elapsed();
|
||||
|
||||
let proof_bytes = bincode::serde::encode_to_vec(&proof, bincode::config::legacy())
|
||||
.map_err(AirbenderError::BincodeEncode)?;
|
||||
|
||||
Ok((
|
||||
public_values,
|
||||
Proof::Compressed(proof_bytes),
|
||||
ProgramProvingReport::new(proving_time),
|
||||
))
|
||||
}
|
||||
|
||||
fn verify(&self, proof: &Proof) -> Result<PublicValues, zkVMError> {
|
||||
let Proof::Compressed(proof) = proof else {
|
||||
return Err(zkVMError::other("Only Compressed proof kind is supported."));
|
||||
};
|
||||
|
||||
let (proof, _): (ProgramProof, _) =
|
||||
bincode::serde::decode_from_slice(proof, bincode::config::legacy())
|
||||
.map_err(AirbenderError::BincodeDecode)?;
|
||||
|
||||
let public_values = self.sdk.verify(&proof)?;
|
||||
|
||||
Ok(public_values)
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
NAME
|
||||
}
|
||||
|
||||
fn sdk_version(&self) -> &'static str {
|
||||
SDK_VERSION
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{
|
||||
EreAirbender,
|
||||
compiler::{AirbenderProgram, RustRv32ima},
|
||||
};
|
||||
use ere_test_utils::{
|
||||
host::{TestCase, run_zkvm_execute, run_zkvm_prove, testing_guest_directory},
|
||||
program::basic::BasicProgramInput,
|
||||
};
|
||||
use ere_zkvm_interface::{Compiler, ProofKind, ProverResourceType, zkVM};
|
||||
use std::sync::OnceLock;
|
||||
|
||||
fn basic_program() -> AirbenderProgram {
|
||||
static PROGRAM: OnceLock<AirbenderProgram> = OnceLock::new();
|
||||
PROGRAM
|
||||
.get_or_init(|| {
|
||||
RustRv32ima
|
||||
.compile(&testing_guest_directory("airbender", "basic"))
|
||||
.unwrap()
|
||||
})
|
||||
.clone()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_execute() {
|
||||
let program = basic_program();
|
||||
let zkvm = EreAirbender::new(program, ProverResourceType::Cpu);
|
||||
|
||||
let test_case = BasicProgramInput::valid().into_output_sha256();
|
||||
run_zkvm_execute(&zkvm, &test_case);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_execute_invalid_input() {
|
||||
let program = basic_program();
|
||||
let zkvm = EreAirbender::new(program, ProverResourceType::Cpu);
|
||||
|
||||
for input in [Vec::new(), BasicProgramInput::invalid().serialized_input()] {
|
||||
zkvm.execute(&input).unwrap_err();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_prove() {
|
||||
let program = basic_program();
|
||||
let zkvm = EreAirbender::new(program, ProverResourceType::Cpu);
|
||||
|
||||
let test_case = BasicProgramInput::valid().into_output_sha256();
|
||||
run_zkvm_execute(&zkvm, &test_case);
|
||||
run_zkvm_prove(&zkvm, &test_case);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_prove_invalid_input() {
|
||||
let program = basic_program();
|
||||
let zkvm = EreAirbender::new(program, ProverResourceType::Cpu);
|
||||
|
||||
for input in [Vec::new(), BasicProgramInput::invalid().serialized_input()] {
|
||||
zkvm.prove(&input, ProofKind::default()).unwrap_err();
|
||||
}
|
||||
}
|
||||
}
|
||||
35
docker/airbender/Dockerfile.base
Normal file
35
docker/airbender/Dockerfile.base
Normal file
@@ -0,0 +1,35 @@
|
||||
ARG BASE_IMAGE=ere-base:latest
|
||||
ARG BASE_CUDA_IMAGE=ere-base:latest-cuda
|
||||
|
||||
# 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}
|
||||
|
||||
# Set default toolchain to nightly
|
||||
RUN rustup default nightly
|
||||
|
||||
ARG CUDA
|
||||
|
||||
# Default to build for RTX 50 series
|
||||
ARG CUDA_ARCH=sm_120
|
||||
|
||||
# Env read by Airbender crate `gpu_prover`, only taking the numeric part
|
||||
ARG CUDAARCHS=${CUDA_ARCH#sm_}
|
||||
|
||||
# Copy the Airbender SDK installer script from the workspace context
|
||||
COPY --chmod=755 scripts/sdk_installers/install_airbender_sdk.sh /tmp/install_airbender_sdk.sh
|
||||
|
||||
# Run the Airbender SDK installation script.
|
||||
# This script installs airbender-cli.
|
||||
RUN /tmp/install_airbender_sdk.sh && rm /tmp/install_airbender_sdk.sh
|
||||
|
||||
# Verify airbender-cli is accessible with the correct toolchain
|
||||
RUN airbender-cli --version
|
||||
|
||||
# Add `rust-src` component to enable std build for nightly rust.
|
||||
RUN rustup component add rust-src
|
||||
|
||||
CMD ["/bin/bash"]
|
||||
34
docker/airbender/Dockerfile.compiler
Normal file
34
docker/airbender/Dockerfile.compiler
Normal file
@@ -0,0 +1,34 @@
|
||||
ARG BASE_ZKVM_IMAGE=ere-base-airbender:latest
|
||||
ARG RUNTIME_IMAGE=ubuntu:24.04
|
||||
|
||||
FROM $BASE_ZKVM_IMAGE AS build_stage
|
||||
|
||||
COPY . /ere
|
||||
|
||||
WORKDIR /ere
|
||||
|
||||
RUN cargo build --release --package ere-compiler --bin ere-compiler --features airbender \
|
||||
&& mkdir bin && mv target/release/ere-compiler bin/ere-compiler \
|
||||
&& cargo clean && rm -rf $CARGO_HOME/registry/src $CARGO_HOME/registry/cache
|
||||
|
||||
FROM $RUNTIME_IMAGE AS runtime_stage
|
||||
|
||||
# Install common dependencies and build tools
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
build-essential \
|
||||
ca-certificates \
|
||||
&& apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Copy Rust
|
||||
COPY --from=build_stage /usr/local/cargo /usr/local/cargo
|
||||
COPY --from=build_stage /usr/local/rustup /usr/local/rustup
|
||||
|
||||
# Add Rust to path
|
||||
ENV RUSTUP_HOME=/usr/local/rustup \
|
||||
CARGO_HOME=/usr/local/cargo \
|
||||
PATH=/usr/local/cargo/bin:$PATH
|
||||
|
||||
# Copy ere-compiler
|
||||
COPY --from=build_stage /ere/bin/ere-compiler /ere/bin/ere-compiler
|
||||
|
||||
ENTRYPOINT ["/ere/bin/ere-compiler"]
|
||||
37
docker/airbender/Dockerfile.server
Normal file
37
docker/airbender/Dockerfile.server
Normal file
@@ -0,0 +1,37 @@
|
||||
ARG BASE_ZKVM_IMAGE=ere-base-airbender:latest
|
||||
ARG BASE_ZKVM_CUDA_IMAGE=ere-base-airbender:latest-cuda
|
||||
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_ZKVM_IMAGE AS base
|
||||
FROM $BASE_ZKVM_CUDA_IMAGE AS base_cuda
|
||||
FROM base${CUDA:+_cuda} AS build_stage
|
||||
|
||||
COPY . /ere
|
||||
|
||||
WORKDIR /ere
|
||||
|
||||
ARG CUDA
|
||||
ARG RUSTFLAGS="-Ctarget-cpu=native"
|
||||
|
||||
RUN cargo build --release --package ere-server --bin ere-server --features airbender${CUDA:+,cuda} \
|
||||
&& mkdir bin && mv target/release/ere-server bin/ere-server \
|
||||
&& cargo clean && rm -rf $CARGO_HOME/registry/src $CARGO_HOME/registry/cache
|
||||
|
||||
FROM $RUNTIME_IMAGE AS runtime
|
||||
FROM $RUNTIME_CUDA_IMAGE AS runtime_cuda
|
||||
FROM runtime${CUDA:+_cuda} AS runtime_stage
|
||||
|
||||
# Copy airbender-cli
|
||||
COPY --from=build_stage /usr/local/cargo/bin/airbender-cli /usr/local/cargo/bin/airbender-cli
|
||||
|
||||
# Add airbender-cli to path
|
||||
ENV PATH=/usr/local/cargo/bin:$PATH
|
||||
|
||||
# Copy ere-server
|
||||
COPY --from=build_stage /ere/bin/ere-server /ere/bin/ere-server
|
||||
|
||||
ENTRYPOINT ["/ere/bin/ere-server"]
|
||||
@@ -17,7 +17,7 @@ COPY --chmod=755 scripts/sdk_installers/install_nexus_sdk.sh /tmp/install_nexus_
|
||||
# Run the Nexus SDK installation script.
|
||||
# This script installs the specific Rust toolchain (nightly-2025-04-06)
|
||||
# and installs cargo-nexus
|
||||
# The CARGO_HOME from ere-base (e.g., /root/.cargo) will be used, and cargo-nexus will be in its bin.
|
||||
# The CARGO_HOME from ere-base (e.g., /usr/local/cargo) will be used, and cargo-nexus will be in its bin.
|
||||
RUN /tmp/install_nexus_sdk.sh && rm /tmp/install_nexus_sdk.sh # Clean up the script
|
||||
|
||||
# Verify Nexus installation
|
||||
|
||||
@@ -17,7 +17,7 @@ COPY --chmod=755 scripts/sdk_installers/install_pico_sdk.sh /tmp/install_pico_sd
|
||||
# Run the Pico SDK installation script.
|
||||
# This script installs the specific Rust toolchain (nightly-2025-08-04)
|
||||
# and installs pico-cli (as cargo-pico).
|
||||
# The CARGO_HOME from ere-base (e.g., /root/.cargo) will be used, and cargo-pico will be in its bin.
|
||||
# The CARGO_HOME from ere-base (e.g., /usr/local/cargo) will be used, and cargo-pico will be in its bin.
|
||||
RUN /tmp/install_pico_sdk.sh && rm /tmp/install_pico_sdk.sh # Clean up the script
|
||||
|
||||
# Verify Pico installation
|
||||
|
||||
51
scripts/sdk_installers/install_airbender_sdk.sh
Executable file
51
scripts/sdk_installers/install_airbender_sdk.sh
Executable file
@@ -0,0 +1,51 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# --- Utility functions (duplicated) ---
|
||||
# Checks if a tool is installed and available in PATH.
|
||||
is_tool_installed() {
|
||||
command -v "$1" &> /dev/null
|
||||
}
|
||||
|
||||
# Ensures a tool is installed. Exits with an error if not.
|
||||
ensure_tool_installed() {
|
||||
local tool_name="$1"
|
||||
local purpose_message="$2"
|
||||
if ! is_tool_installed "${tool_name}"; then
|
||||
echo "Error: Required tool '${tool_name}' could not be found." >&2
|
||||
if [ -n "${purpose_message}" ]; then
|
||||
echo " It is needed ${purpose_message}." >&2
|
||||
fi
|
||||
echo " Please install it first and ensure it is in your PATH." >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
# --- End of Utility functions ---
|
||||
|
||||
ensure_tool_installed "rustup" "to manage Rust toolchains"
|
||||
ensure_tool_installed "git" "to install airbender-cli from a git repository"
|
||||
ensure_tool_installed "cargo" "to build and install Rust packages"
|
||||
|
||||
AIRBENDER_CLI_VERSION_TAG="v0.5.0"
|
||||
|
||||
# Install airbender-cli using the specified toolchain and version tag
|
||||
echo "Installing airbender-cli (version ${AIRBENDER_CLI_VERSION_TAG}) from GitHub repository (matter-labs/zksync-airbender)..."
|
||||
cargo +nightly install --locked --git https://github.com/matter-labs/zksync-airbender.git --tag "${AIRBENDER_CLI_VERSION_TAG}" ${CUDA:+-F gpu} cli
|
||||
|
||||
# Rename cli to airbender-cli
|
||||
CARGO_HOME=${CARGO_HOME:-$HOME/.cargo}
|
||||
mv $CARGO_HOME/bin/cli $CARGO_HOME/bin/airbender-cli
|
||||
|
||||
# Verify airbender-cli installation
|
||||
echo "Verifying airbender-cli installation..."
|
||||
if airbender-cli --version; then
|
||||
echo "airbender-cli installation verified successfully."
|
||||
else
|
||||
echo "Error: 'airbender-cli --version' failed. airbender-cli might not have installed correctly." >&2
|
||||
echo " Ensure $CARGO_HOME/bin is in your PATH for new shells." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Install cargo-binutils to objcopy ELF to binary file
|
||||
rustup +nightly component add llvm-tools
|
||||
cargo install cargo-binutils
|
||||
10
tests/airbender/basic/Cargo.toml
Normal file
10
tests/airbender/basic/Cargo.toml
Normal file
@@ -0,0 +1,10 @@
|
||||
[package]
|
||||
name = "ere-test-airbender-guest"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
riscv_common = { git = "https://github.com/matter-labs/zksync-airbender", features = ["custom_allocator"], tag = "v0.5.0" }
|
||||
ere-test-utils = { path = "../../../crates/test-utils" }
|
||||
|
||||
[workspace]
|
||||
60
tests/airbender/basic/src/airbender_rt.rs
Normal file
60
tests/airbender/basic/src/airbender_rt.rs
Normal file
@@ -0,0 +1,60 @@
|
||||
use core::alloc::{GlobalAlloc, Layout};
|
||||
|
||||
core::arch::global_asm!(include_str!("./asm_reduced.S"));
|
||||
|
||||
#[link_section = ".init.rust"]
|
||||
#[export_name = "_start_rust"]
|
||||
unsafe extern "C" fn start_rust() -> ! {
|
||||
crate::main();
|
||||
unsafe { core::hint::unreachable_unchecked() }
|
||||
}
|
||||
|
||||
/// A simple heap allocator.
|
||||
///
|
||||
/// Allocates memory from left to right, without any deallocation.
|
||||
struct SimpleAlloc;
|
||||
|
||||
unsafe impl GlobalAlloc for SimpleAlloc {
|
||||
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
||||
unsafe { sys_alloc_aligned(layout.size(), layout.align()) }
|
||||
}
|
||||
|
||||
unsafe fn dealloc(&self, _: *mut u8, _: Layout) {}
|
||||
}
|
||||
|
||||
#[global_allocator]
|
||||
static HEAP: SimpleAlloc = SimpleAlloc;
|
||||
|
||||
static mut HEAP_POS: usize = 0;
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn sys_alloc_aligned(bytes: usize, align: usize) -> *mut u8 {
|
||||
unsafe extern "C" {
|
||||
// start/end of heap defined in `link.x`.
|
||||
unsafe static _sheap: u8;
|
||||
unsafe static _eheap: u8;
|
||||
}
|
||||
|
||||
// SAFETY: Single threaded, so nothing else can touch this while we're working.
|
||||
let mut heap_pos = unsafe { HEAP_POS };
|
||||
|
||||
if heap_pos == 0 {
|
||||
heap_pos = unsafe { (&_sheap) as *const u8 as usize };
|
||||
}
|
||||
|
||||
let offset = heap_pos & (align - 1);
|
||||
if offset != 0 {
|
||||
heap_pos += align - offset;
|
||||
}
|
||||
|
||||
let ptr = heap_pos as *mut u8;
|
||||
let (heap_pos, overflowed) = heap_pos.overflowing_add(bytes);
|
||||
|
||||
let eheap = unsafe { (&_eheap) as *const u8 as usize };
|
||||
if overflowed || heap_pos > eheap {
|
||||
panic!("Heap exhausted");
|
||||
}
|
||||
|
||||
unsafe { HEAP_POS = heap_pos };
|
||||
ptr
|
||||
}
|
||||
160
tests/airbender/basic/src/asm_reduced.S
Normal file
160
tests/airbender/basic/src/asm_reduced.S
Normal file
@@ -0,0 +1,160 @@
|
||||
/* Copied from https://github.com/matter-labs/zksync-airbender/blob/v0.5.0/examples/scripts/asm/asm_reduced.S */
|
||||
|
||||
/*
|
||||
Entry point of all programs (_start).
|
||||
|
||||
It initializes DWARF call frame information, the stack pointer, the
|
||||
frame pointer (needed for closures to work in start_rust) and the global
|
||||
pointer. Then it calls _start_rust.
|
||||
*/
|
||||
|
||||
.section .init, "ax"
|
||||
.global _start
|
||||
|
||||
_start:
|
||||
/* Jump to the absolute address defined by the linker script. */
|
||||
// for 32bit
|
||||
# lui ra, %hi(_abs_start)
|
||||
# jr %lo(_abs_start)(ra)
|
||||
|
||||
la ra, _abs_start
|
||||
jr ra
|
||||
|
||||
_abs_start:
|
||||
.cfi_startproc
|
||||
.cfi_undefined ra
|
||||
|
||||
.option push
|
||||
.option norelax
|
||||
la gp, __global_pointer$
|
||||
.option pop
|
||||
|
||||
// Assume single core, and put SP to the very top address of the stack region
|
||||
la sp, _sstack
|
||||
|
||||
// Set frame pointer
|
||||
add s0, sp, zero
|
||||
|
||||
jal zero, _start_rust
|
||||
|
||||
.cfi_endproc
|
||||
|
||||
/*
|
||||
Machine trap entry point (_machine_start_trap)
|
||||
*/
|
||||
.section .trap, "ax"
|
||||
.global machine_default_start_trap
|
||||
.align 4
|
||||
machine_default_start_trap:
|
||||
// We assume that exception stack is always saved to MSCRATCH
|
||||
|
||||
// so we swap it with x31
|
||||
csrrw x31, mscratch, x31
|
||||
|
||||
// write to exception stack
|
||||
# sw x31, -4(sp)
|
||||
sw x30, -8(x31)
|
||||
sw x29, -12(x31)
|
||||
sw x28, -16(x31)
|
||||
sw x27, -20(x31)
|
||||
sw x26, -24(x31)
|
||||
sw x25, -28(x31)
|
||||
sw x24, -32(x31)
|
||||
sw x23, -36(x31)
|
||||
sw x22, -40(x31)
|
||||
sw x21, -44(x31)
|
||||
sw x20, -48(x31)
|
||||
sw x19, -52(x31)
|
||||
sw x18, -56(x31)
|
||||
sw x17, -60(x31)
|
||||
sw x16, -64(x31)
|
||||
sw x15, -68(x31)
|
||||
sw x14, -72(x31)
|
||||
sw x13, -76(x31)
|
||||
sw x12, -80(x31)
|
||||
sw x11, -84(x31)
|
||||
sw x10, -88(x31)
|
||||
sw x9, -92(x31)
|
||||
sw x8, -96(x31)
|
||||
sw x7, -100(x31)
|
||||
sw x6, -104(x31)
|
||||
sw x5, -108(x31)
|
||||
sw x4, -112(x31)
|
||||
sw x3, -116(x31)
|
||||
sw x2, -120(x31)
|
||||
sw x1, -124(x31)
|
||||
|
||||
// we will not restore it, so we are ok to avoid write
|
||||
# sw x0, -128(x31)
|
||||
|
||||
// move valid sp into a0,
|
||||
mv a0, x31
|
||||
csrrw x31, mscratch, x0
|
||||
sw x31, -4(a0)
|
||||
// restore sp
|
||||
mv sp, a0
|
||||
// sp is valid now
|
||||
|
||||
addi sp, sp, -128
|
||||
// pass pointer as first argument
|
||||
add a0, sp, zero
|
||||
|
||||
jal ra, _machine_start_trap_rust
|
||||
|
||||
// set return address into mepc
|
||||
csrw mepc, a0
|
||||
|
||||
// save original SP to mscratch for now
|
||||
lw a0, 8(sp) // it's original sp that we saved in the stack
|
||||
csrw mscratch, a0 // save it for now
|
||||
|
||||
// restore everything we saved
|
||||
|
||||
// it's illegal instruction, so we skip. Anyway can not overwrite x0
|
||||
# lw x0, 0(sp)
|
||||
|
||||
lw x1, 4(sp)
|
||||
# lw x2, 8(sp) // do not overwrite SP yet
|
||||
lw x3, 12(sp)
|
||||
lw x4, 16(sp)
|
||||
lw x5, 20(sp)
|
||||
lw x6, 24(sp)
|
||||
lw x7, 28(sp)
|
||||
lw x8, 32(sp)
|
||||
lw x9, 36(sp)
|
||||
lw x10, 40(sp)
|
||||
lw x11, 44(sp)
|
||||
lw x12, 48(sp)
|
||||
lw x13, 52(sp)
|
||||
lw x14, 56(sp)
|
||||
lw x15, 60(sp)
|
||||
lw x16, 64(sp)
|
||||
lw x17, 68(sp)
|
||||
lw x18, 72(sp)
|
||||
lw x19, 76(sp)
|
||||
lw x20, 80(sp)
|
||||
lw x21, 84(sp)
|
||||
lw x22, 88(sp)
|
||||
lw x23, 92(sp)
|
||||
lw x24, 96(sp)
|
||||
lw x25, 100(sp)
|
||||
lw x26, 104(sp)
|
||||
lw x27, 108(sp)
|
||||
lw x28, 112(sp)
|
||||
lw x29, 116(sp)
|
||||
lw x30, 120(sp)
|
||||
lw x31, 124(sp)
|
||||
|
||||
addi sp, sp, 128
|
||||
// we popped everything from the stack
|
||||
// now save current exception SP to mscratch,
|
||||
// and put original SP back
|
||||
csrrw sp, mscratch, sp
|
||||
|
||||
mret
|
||||
|
||||
/* Make sure there is an abort when linking */
|
||||
.section .text.abort
|
||||
.globl abort
|
||||
abort:
|
||||
j abort
|
||||
42
tests/airbender/basic/src/main.rs
Normal file
42
tests/airbender/basic/src/main.rs
Normal file
@@ -0,0 +1,42 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![no_builtins]
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(allocator_api)]
|
||||
#![feature(generic_const_exprs)]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
use alloc::vec::Vec;
|
||||
use core::{array, iter::repeat_with};
|
||||
use ere_test_utils::{
|
||||
guest::{Digest, Platform, Sha256},
|
||||
program::{basic::BasicProgram, Program},
|
||||
};
|
||||
use riscv_common::{csr_read_word, zksync_os_finish_success};
|
||||
|
||||
mod airbender_rt;
|
||||
|
||||
struct AirbenderPlatform;
|
||||
|
||||
impl Platform for AirbenderPlatform {
|
||||
fn read_input() -> Vec<u8> {
|
||||
let len = csr_read_word() as usize;
|
||||
repeat_with(csr_read_word)
|
||||
.take(len.div_ceil(4))
|
||||
.flat_map(|word| word.to_le_bytes())
|
||||
.take(len)
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn write_output(output: &[u8]) {
|
||||
let digest = Sha256::digest(output);
|
||||
let words = array::from_fn(|i| u32::from_le_bytes(array::from_fn(|j| digest[4 * i + j])));
|
||||
zksync_os_finish_success(&words);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
fn main() {
|
||||
BasicProgram::run::<AirbenderPlatform>();
|
||||
}
|
||||
Reference in New Issue
Block a user