Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ jobs:
- name: Set up Rust/Cargo
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
toolchain: stable
toolchain: nightly
components: clippy, rustfmt

- name: Verify installation
Expand All @@ -70,7 +70,7 @@ jobs:

- name: Run clippy on hosts
run: |
cargo clippy --manifest-path rust/Cargo.toml --workspace -- -D warnings
cargo +nightly clippy --manifest-path rust/Cargo.toml --workspace -- -D warnings

- name: Lint
run: zig fmt --check .
Expand Down
37 changes: 35 additions & 2 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const zkvm_targets: []const zkvmTarget = &.{
.{ .name = "ziren", .triplet = "mipsel-freestanding-none", .cpu_features = "mips32r2" },
};

const ProverChoice = enum { dummy, risc0, openvm, all };
const ProverChoice = enum { dummy, risc0, openvm, sp1, ziren, all };

fn setTestRunLabel(b: *Builder, run_step: *std.Build.Step.Run, name: []const u8) void {
run_step.step.name = b.fmt("test {s}", .{name});
Expand Down Expand Up @@ -53,9 +53,23 @@ fn addRustGlueLib(b: *Builder, comp: *Builder.Step.Compile, target: Builder.Reso
comp.addObjectFile(b.path("rust/target/openvm-release/libmultisig_glue.a"));
comp.addObjectFile(b.path("rust/target/openvm-release/liblibp2p_glue.a"));
},
.sp1 => {
comp.addObjectFile(b.path("rust/target/sp1-release/libsp1_glue.a"));
comp.addObjectFile(b.path("rust/target/sp1-release/libhashsig_glue.a"));
comp.addObjectFile(b.path("rust/target/sp1-release/libmultisig_glue.a"));
comp.addObjectFile(b.path("rust/target/sp1-release/liblibp2p_glue.a"));
},
.ziren => {
comp.addObjectFile(b.path("rust/target/ziren-release/libziren_glue.a"));
comp.addObjectFile(b.path("rust/target/ziren-release/libhashsig_glue.a"));
comp.addObjectFile(b.path("rust/target/ziren-release/libmultisig_glue.a"));
comp.addObjectFile(b.path("rust/target/ziren-release/liblibp2p_glue.a"));
},
.all => {
comp.addObjectFile(b.path("rust/target/release/librisc0_glue.a"));
comp.addObjectFile(b.path("rust/target/release/libopenvm_glue.a"));
comp.addObjectFile(b.path("rust/target/release/libsp1_glue.a"));
comp.addObjectFile(b.path("rust/target/release/libziren_glue.a"));
comp.addObjectFile(b.path("rust/target/release/libhashsig_glue.a"));
comp.addObjectFile(b.path("rust/target/release/libmultisig_glue.a"));
comp.addObjectFile(b.path("rust/target/release/liblibp2p_glue.a"));
Expand All @@ -67,6 +81,13 @@ fn addRustGlueLib(b: *Builder, comp: *Builder.Step.Compile, target: Builder.Reso
comp.linkFramework("CoreFoundation");
comp.linkFramework("SystemConfiguration");
comp.linkFramework("Security");
} else if (target.result.os.tag == .linux) {
// Rust's native_tls crate uses OpenSSL on Linux (via openssl-sys).
// The prover glue libraries (risc0, sp1, etc.) pull in reqwest →
// hyper_tls → native_tls → openssl, so we need to link against
// libssl and libcrypto.
comp.linkSystemLibrary("ssl");
comp.linkSystemLibrary("crypto");
Comment on lines +88 to +90
Copy link

Copilot AI Mar 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On Linux, addRustGlueLib now unconditionally links ssl and crypto for every build target. This introduces a hard system dependency on OpenSSL even for -Dprover=dummy builds, and can break builds in minimal environments where libssl/libcrypto aren’t installed. Consider linking these libraries only for provers/crates that actually require OpenSSL (or switching the Rust dependencies to rustls where feasible), and/or gating this behind a build option.

Suggested change
// libssl and libcrypto.
comp.linkSystemLibrary("ssl");
comp.linkSystemLibrary("crypto");
// libssl and libcrypto when those provers are enabled.
switch (prover) {
.dummy => {},
else => {
comp.linkSystemLibrary("ssl");
comp.linkSystemLibrary("crypto");
},
}

Copilot uses AI. Check for mistakes.
}
}

Expand All @@ -78,7 +99,7 @@ pub fn build(b: *Builder) !void {
const git_version = b.option([]const u8, "git_version", "Git commit hash for version") orelse "unknown";

// Get prover choice (default to dummy)
const prover_option = b.option([]const u8, "prover", "Choose prover: dummy, risc0, openvm, or all (default: dummy)") orelse "dummy";
const prover_option = b.option([]const u8, "prover", "Choose prover: dummy, risc0, openvm, sp1, ziren, or all (default: dummy)") orelse "dummy";
const prover = std.meta.stringToEnum(ProverChoice, prover_option) orelse .dummy;

const build_rust_lib_steps = build_rust_project(b, "rust", prover);
Expand Down Expand Up @@ -154,6 +175,8 @@ pub fn build(b: *Builder) !void {
build_options.addOption([]const u8, "prover", @tagName(prover));
build_options.addOption(bool, "has_risc0", prover == .risc0 or prover == .all);
build_options.addOption(bool, "has_openvm", prover == .openvm or prover == .all);
build_options.addOption(bool, "has_sp1", prover == .sp1 or prover == .all);
build_options.addOption(bool, "has_ziren", prover == .ziren or prover == .all);
const use_poseidon = b.option(bool, "use_poseidon", "Use Poseidon SSZ hasher (default: false)") orelse false;
build_options.addOption(bool, "use_poseidon", use_poseidon);
const build_options_module = build_options.createModule();
Expand Down Expand Up @@ -706,6 +729,16 @@ fn build_rust_project(b: *Builder, path: []const u8, prover: ProverChoice) *Buil
"build", "--profile", "openvm-release", "-p", "libp2p-glue", "-p",
"openvm-glue", "-p", "hashsig-glue", "-p", "multisig-glue",
}),
.sp1 => b.addSystemCommand(&.{
"cargo", "+nightly", "-C", path, "-Z", "unstable-options",
"build", "--profile", "sp1-release", "-p", "libp2p-glue", "-p",
"sp1-glue", "-p", "hashsig-glue", "-p", "multisig-glue",
}),
.ziren => b.addSystemCommand(&.{
"cargo", "+nightly", "-C", path, "-Z", "unstable-options",
"build", "--profile", "ziren-release", "-p", "libp2p-glue", "-p",
"ziren-glue", "-p", "hashsig-glue", "-p", "multisig-glue",
}),
.all => b.addSystemCommand(&.{
"cargo", "+nightly", "-C", path, "-Z", "unstable-options",
"build", "--release", "--all",
Expand Down
2 changes: 2 additions & 0 deletions pkgs/cli/src/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,8 @@ fn mainInner() !void {
.risc0 => break :blk .{ .risc0 = .{ .program_path = "zig-out/bin/risc0_runtime.elf" } },
.powdr => return error.PowdrIsDeprecated,
.openvm => break :blk .{ .openvm = .{ .program_path = "zig-out/bin/zeam-stf-openvm", .result_path = "/tmp/openvm-results" } },
.sp1 => break :blk .{ .sp1 = .{ .program_path = "zig-out/bin/zeam-stf-sp1" } },
.ziren => break :blk .{ .ziren = .{ .program_path = "zig-out/bin/zeam-stf-ziren" } },
.dummy => break :blk .{ .dummy = .{} },
},
.logger = logger,
Expand Down
64 changes: 64 additions & 0 deletions pkgs/state-proving-manager/src/manager.zig
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,56 @@ fn openvm_verify_stub(binary_path: [*]const u8, binary_path_len: usize, receipt:
const openvm_prove_fn = if (build_options.has_openvm) openvm_prove else openvm_prove_stub;
const openvm_verify_fn = if (build_options.has_openvm) openvm_verify else openvm_verify_stub;

// Conditionally declare extern functions - these will only be linked if the library is included
extern fn sp1_prove(serialized: [*]const u8, len: usize, binary_path: [*]const u8, binary_path_length: usize, output: [*]u8, output_len: usize) callconv(.c) u32;
extern fn sp1_verify(binary_path: [*]const u8, binary_path_len: usize, receipt: [*]const u8, receipt_len: usize) callconv(.c) bool;

fn sp1_prove_stub(serialized: [*]const u8, len: usize, binary_path: [*]const u8, binary_path_length: usize, output: [*]u8, output_len: usize) u32 {
_ = serialized;
_ = len;
_ = binary_path;
_ = binary_path_length;
_ = output;
_ = output_len;
@panic("SP1 support not compiled in");
}

fn sp1_verify_stub(binary_path: [*]const u8, binary_path_len: usize, receipt: [*]const u8, receipt_len: usize) bool {
_ = binary_path;
_ = binary_path_len;
_ = receipt;
_ = receipt_len;
@panic("SP1 support not compiled in");
}

const sp1_prove_fn = if (build_options.has_sp1) sp1_prove else sp1_prove_stub;
const sp1_verify_fn = if (build_options.has_sp1) sp1_verify else sp1_verify_stub;

// Conditionally declare extern functions - these will only be linked if the library is included
extern fn ziren_prove(serialized: [*]const u8, len: usize, binary_path: [*]const u8, binary_path_length: usize, output: [*]u8, output_len: usize) callconv(.c) u32;
extern fn ziren_verify(binary_path: [*]const u8, binary_path_len: usize, receipt: [*]const u8, receipt_len: usize) callconv(.c) bool;

fn ziren_prove_stub(serialized: [*]const u8, len: usize, binary_path: [*]const u8, binary_path_length: usize, output: [*]u8, output_len: usize) u32 {
_ = serialized;
_ = len;
_ = binary_path;
_ = binary_path_length;
_ = output;
_ = output_len;
@panic("Ziren support not compiled in");
}

fn ziren_verify_stub(binary_path: [*]const u8, binary_path_len: usize, receipt: [*]const u8, receipt_len: usize) bool {
_ = binary_path;
_ = binary_path_len;
_ = receipt;
_ = receipt_len;
@panic("Ziren support not compiled in");
}

const ziren_prove_fn = if (build_options.has_ziren) ziren_prove else ziren_prove_stub;
const ziren_verify_fn = if (build_options.has_ziren) ziren_verify else ziren_verify_stub;

const PowdrConfig = struct {
program_path: []const u8,
output_dir: []const u8,
Expand All @@ -78,6 +128,14 @@ const OpenVMConfig = struct {
result_path: []const u8,
};

const SP1Config = struct {
program_path: []const u8,
};

const ZirenConfig = struct {
program_path: []const u8,
};

const DummyConfig = struct {
// Empty struct - dummy prover doesn't need configuration
};
Expand All @@ -86,6 +144,8 @@ const ZKVMConfig = union(enum) {
powdr: PowdrConfig,
risc0: Risc0Config,
openvm: OpenVMConfig,
sp1: SP1Config,
ziren: ZirenConfig,
dummy: DummyConfig,
};
pub const ZKVMs = std.meta.Tag(ZKVMConfig);
Expand Down Expand Up @@ -127,6 +187,8 @@ pub fn prove_transition(state: types.BeamState, block: types.BeamBlock, opts: ZK
.powdr => return error.RiscVPowdrIsDeprecated,
.risc0 => |risc0cfg| risc0_prove_fn(serialized.items.ptr, serialized.items.len, risc0cfg.program_path.ptr, risc0cfg.program_path.len, output.ptr, output.len),
.openvm => |openvmcfg| openvm_prove_fn(serialized.items.ptr, serialized.items.len, output.ptr, output.len, openvmcfg.program_path.ptr, openvmcfg.program_path.len, openvmcfg.result_path.ptr, openvmcfg.result_path.len),
.sp1 => |sp1cfg| sp1_prove_fn(serialized.items.ptr, serialized.items.len, sp1cfg.program_path.ptr, sp1cfg.program_path.len, output.ptr, output.len),
.ziren => |zirencfg| ziren_prove_fn(serialized.items.ptr, serialized.items.len, zirencfg.program_path.ptr, zirencfg.program_path.len, output.ptr, output.len),
.dummy => blk: {
// For dummy prover, we actually run the transition function to test it
// This ensures the transition function works and tests allocations
Expand Down Expand Up @@ -161,6 +223,8 @@ pub fn verify_transition(stf_proof: types.BeamSTFProof, state_root: types.Bytes3
const valid = switch (opts.zkvm) {
.risc0 => |risc0cfg| risc0_verify_fn(risc0cfg.program_path.ptr, risc0cfg.program_path.len, stf_proof.proof.ptr, stf_proof.proof.len),
.openvm => |openvmcfg| openvm_verify_fn(openvmcfg.program_path.ptr, openvmcfg.program_path.len, stf_proof.proof.ptr, stf_proof.proof.len),
.sp1 => |sp1cfg| sp1_verify_fn(sp1cfg.program_path.ptr, sp1cfg.program_path.len, stf_proof.proof.ptr, stf_proof.proof.len),
.ziren => |zirencfg| ziren_verify_fn(zirencfg.program_path.ptr, zirencfg.program_path.len, stf_proof.proof.ptr, stf_proof.proof.len),
.dummy => blk: {
const expected_proof = "DUMMY_PROOF_V1";
if (stf_proof.proof.len >= expected_proof.len) {
Expand Down
Loading
Loading