Skip to content

Commit 10e3bb9

Browse files
authored
Reproducible ELF builds for SP1 program in Docker (#41)
1 parent ac297a2 commit 10e3bb9

File tree

9 files changed

+41
-36
lines changed

9 files changed

+41
-36
lines changed

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ zkvm-common = { path = "zkVM/common", default-features = false, version = "0.2.2
1717
anyhow = "1.0"
1818
clap = { version = "4.5", features = ["derive", "env"] }
1919
hex = "0.4"
20-
sha2 = "=0.10.8"
2120
sp1-zkvm = "5.1"
2221
sp1-sdk = "5.1"
2322
sp1-build = "5.1"
@@ -43,9 +42,10 @@ rustls = "0.23"
4342
tokio-rustls = "0.26"
4443
rustls-pemfile = "2.2"
4544

45+
sha2 = "=0.10.8"
4646
[patch.crates-io]
4747
# TODO: update to 5.0?
4848
sha2 = { git = "https://github.com/sp1-patches/RustCrypto-hashes", tag = "patch-sha2-0.10.8-sp1-4.0.0" }
4949

5050
[workspace.features]
51-
reproducible-elf = ["service/reproducible-elf"]
51+
reproducible-elf = ["service/reproducible-elf", "zkVM/sp1/reproducible-elf"]

Dockerfile

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
FROM nvidia/cuda:12.9.1-devel-ubuntu24.04 AS base-dev
33

44
RUN apt-get update && DEBIAN_FRONTEND=noninteractive \
5-
apt-get install --no-install-recommends -y \
6-
clang libclang-dev docker.io curl tar build-essential pkg-config git ca-certificates gnupg2 \
7-
&& rm -rf /var/lib/apt/lists/*
5+
apt-get install --no-install-recommends -y \
6+
clang libclang-dev docker.io curl tar build-essential pkg-config git ca-certificates gnupg2 \
7+
&& rm -rf /var/lib/apt/lists/*
88

99
ENV GO_VERSION=1.24.5
1010
ENV GO_URL="https://go.dev/dl/go${GO_VERSION}.linux-amd64.tar.gz"
@@ -26,7 +26,7 @@ RUN cargo install cargo-chef
2626

2727
# https://docs.succinct.xyz/docs/sp1/getting-started/install
2828
RUN curl -L https://sp1up.succinct.xyz | bash && \
29-
/root/.sp1/bin/sp1up
29+
/root/.sp1/bin/sp1up
3030

3131
####################################################################################################
3232
FROM base-dev AS planner
@@ -44,20 +44,20 @@ WORKDIR /app
4444
COPY --from=planner /app/recipe.json ./
4545

4646
RUN --mount=type=cache,id=target_cache,target=/app/target \
47-
cargo chef cook --release --recipe-path recipe.json
47+
cargo chef cook --release --recipe-path recipe.json
4848

4949
COPY . .
5050

5151
# Build SP1 ELF to be proven (with optimizations)
52-
# TODO: need to use `cargo prove --docker` for repoducible builds?
52+
# WARNING: we do NOT assume `cargo prove build --docker` is required for identical ELF
5353
RUN --mount=type=cache,id=target_cache,target=/app/target \
54-
RUSTFLAGS="-Copt-level=3 -Clto=fat -Ccodegen-units=1 -Cdebuginfo=1 -Cembed-bitcode=yes" /root/.sp1/bin/cargo-prove prove build -p chacha-program
55-
# Build the final binary
56-
# NOTE: default feature is to use --docker ELF
54+
RUSTFLAGS="-Copt-level=3 -Clto=fat -Ccodegen-units=1 -Cdebuginfo=1 -Cembed-bitcode=yes"\
55+
/root/.sp1/bin/cargo-prove prove build -p chacha-program
56+
# Build the final binary, embbeding ELF
5757
RUN --mount=type=cache,id=target_cache,target=/app/target \
58-
cargo build --release --no-default-features && \
59-
strip /app/target/release/pda-proxy && \
60-
cp target/release/pda-proxy /app/pda-proxy # pop out of cache
58+
cargo build --release && \
59+
strip /app/target/release/pda-proxy && \
60+
cp target/release/pda-proxy /app/pda-proxy # pop out of cache
6161

6262
####################################################################################################
6363
FROM nvidia/cuda:12.9.1-base-ubuntu24.04 AS runtime

justfile

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@ default:
33

44
alias r := run-debug
55
alias rr := run-release
6+
alias rrr := run-release-reproducible
67
alias bc := bench-cycles
78
alias db := docker-build
89
alias ds := docker-save
910
alias dl := docker-load
1011
alias dr := docker-run
1112
alias b := build-debug
1213
alias br := build-release
14+
alias brr := build-release-reproducible
1315
alias f := fmt
1416
alias c := clean
1517

@@ -30,7 +32,9 @@ initial-config-installs:
3032
@just sp1 initial-config-installs
3133

3234
_pre-build:
33-
# ALWAYS build with docker
35+
@just sp1 build-elf
36+
37+
_pre-build-reproducible:
3438
@just sp1 build-elf-reproducible
3539

3640
_pre-run:
@@ -40,6 +44,10 @@ _pre-run:
4044
bench-cycles *FLAGS: _pre-build _pre-run
4145
cargo r -r -p sp1-util --bin cli -- --execute
4246

47+
# Run in release mode, zkVM ELF stable with optimizations AND debug logs
48+
run-release-reproducible *FLAGS: _pre-build-reproducible _pre-run
49+
RUST_LOG=pda_proxy=debug cargo r -r --features reproducible-elf -- {{ FLAGS }}
50+
4351
# Run in release mode, with optimizations AND debug logs
4452
run-release *FLAGS: _pre-build _pre-run
4553
RUST_LOG=pda_proxy=debug cargo r -r -- {{ FLAGS }}
@@ -51,7 +59,11 @@ run-debug *FLAGS: _pre-build _pre-run
5159

5260
# Build docker image & tag
5361
docker-build:
54-
DOCKER_BUILDKIT=1 docker build --build-arg BUILDKIT_INLINE_CACHE=1 --tag "$DOCKER_CONTAINER_NAME" --progress=plain .
62+
DOCKER_BUILDKIT=1 docker build \
63+
--build-arg BUILDKIT_INLINE_CACHE=1 \
64+
--tag "$DOCKER_CONTAINER_NAME" \
65+
--progress=plain \
66+
.
5567

5668
# Save docker image to a tar.gz
5769
docker-save:
@@ -70,13 +82,15 @@ docker-run:
7082
docker run --rm -it \
7183
-v /var/run/docker.sock:/var/run/docker.sock \
7284
-v ./service/static:/app/static \
85+
-v $HOME/.sp1/circuits:/root/.sp1/circuits \
7386
-v $PDA_DB_PATH:$PDA_DB_PATH \
7487
--env-file {{ env-settings }} \
75-
--env TLS_CERTS_PATH=/app/static/sample.pem --env TLS_KEY_PATH=/app/static/sample.rsa \
88+
--env TLS_CERTS_PATH=/app/static/sample.pem \
89+
--env TLS_KEY_PATH=/app/static/sample.rsa \
7690
--env RUST_LOG=pda_proxy=debug \
7791
--network=host \
7892
-p $PDA_PORT:$PDA_PORT \
79-
"$DOCKER_CONTAINER_NAME"
93+
$DOCKER_CONTAINER_NAME
8094

8195
# Build in debug mode, no optimizations
8296
build-debug: _pre-build
@@ -86,6 +100,10 @@ build-debug: _pre-build
86100
build-release: _pre-build
87101
cargo b -r
88102

103+
# Build in release mode, enforce ELF build is reproducible includes optimizations
104+
build-release-reproducible: _pre-build-reproducible
105+
cargo b -r --features reproducible-elf
106+
89107
# Scrub build artifacts
90108
clean:
91109
cargo clean

service/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,6 @@ rustls-pemfile.workspace = true
3030
hyper-rustls.workspace = true
3131

3232
[features]
33-
default = ["reproducible-elf"]
33+
default = []
3434

3535
reproducible-elf = []

service/src/internal/runner.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -505,7 +505,7 @@ impl PdaRunner {
505505
job: &Job,
506506
job_key: &[u8],
507507
) -> Result<util::SuccNetJobId, PdaRunnerError> {
508-
debug!("Preparing local SP1 proving");
508+
debug!("Preparing *REMOTE* SP1 proving");
509509
let zk_client_handle = self.get_zk_client_remote().await;
510510
let proof_setup = self
511511
.get_proof_setup_remote(program_id, zk_client_handle.clone())

zkVM/common/Cargo.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,5 @@ rand = { workspace = true, default-features = false, optional = true, features =
1111
sha2 = { workspace = true, optional = true }
1212

1313
[features]
14-
default = ["std", "reproducible-elf"]
14+
default = ["std"]
1515
std = ["rand/os_rng", "sha2"]
16-
reproducible-elf = []

zkVM/common/src/lib.rs

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,3 @@
1-
// Include the binary input file
2-
/// For reproducible builds, you need `cargo prove --docker`
3-
#[cfg(feature = "reproducible-elf")]
4-
pub const CHACHA_ELF: &[u8] = include_bytes!(
5-
"../../../target/elf-compilation/docker/riscv32im-succinct-zkvm-elf/release/chacha-program"
6-
);
7-
8-
#[cfg(not(feature = "reproducible-elf"))]
9-
pub const CHACHA_ELF: &[u8] = include_bytes!(
10-
"../../../target/elf-compilation/riscv32im-succinct-zkvm-elf/release/chacha-program"
11-
);
12-
131
use chacha20::ChaCha20;
142
use chacha20::cipher::{KeyIvInit, StreamCipher};
153

zkVM/sp1/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,6 @@ codegen-units = 1
3333
debug = 1
3434

3535
[features]
36-
default = ["reproducible-elf"]
36+
default = []
3737

3838
reproducible-elf = []

zkVM/sp1/justfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ build-elf-reproducible:
5757
if [ ! -f "$ZK_PROGRAM_REPRODUCIBLE_ELF_PATH" ]; then \
5858
echo -e "Can't find ELF at \`$ZK_PROGRAM_REPRODUCIBLE_ELF_PATH\`.\nAttempting to build it..."; \
5959
RUSTFLAGS="-Copt-level=3 -Clto=fat -Ccodegen-units=1 -Cdebuginfo=1 -Cembed-bitcode=yes" \
60-
echo -r "\n******\nNOTE: the first run will download an sp1 docker image ~5GB\ncheck network usage if you are not seeing any progress on this step...\n"; \
60+
echo -e "\n******\nNOTE: the first run will download an sp1 docker image ~5GB\ncheck network usage if you are not seeing any progress on this step...\n******\n"; \
6161
RUSTFLAGS="-Copt-level=3 -Clto=fat -Ccodegen-units=1 -Cdebuginfo=1 -Cembed-bitcode=yes" cargo prove build --docker -p chacha-program; \
6262
else \
6363
echo "✅ REPRODUCIBLE - ELF Exists, skipping SP1 build"; \

0 commit comments

Comments
 (0)