Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

STR-873 SP1-V4 Update #597

Merged
merged 8 commits into from
Jan 8, 2025
Merged
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
1,706 changes: 736 additions & 970 deletions Cargo.lock

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions crates/zkvm/adapters/sp1/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ borsh.workspace = true
hex.workspace = true
serde.workspace = true
sha2 = { workspace = true }
sp1-primitives = "3.0.0"
sp1-sdk = { version = "3.0.0", optional = true }
sp1-verifier = { git = "https://github.com/succinctlabs/sp1", rev = "2c7868364cb832531e8cafd258aa06fbab079459" } # Note: On new SP1 version, this will be available via SDK
sp1-zkvm = { version = "3.0.0", features = ["verify"], optional = true }
sp1-primitives = "=4.0.0-rc.8"
sp1-sdk = { version = "=4.0.0-rc.8", optional = true }
sp1-verifier = { version = "=4.0.0-rc.8" }
sp1-zkvm = { version = "=4.0.0-rc.8", features = ["verify"], optional = true }
tracing.workspace = true

[features]
Expand Down
47 changes: 37 additions & 10 deletions crates/zkvm/adapters/sp1/src/host.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use std::fmt;

use serde::{de::DeserializeOwned, Serialize};
use sp1_sdk::{HashableKey, ProverClient, SP1ProvingKey, SP1VerifyingKey};
use sp1_sdk::{
network::FulfillmentStrategy, HashableKey, ProverClient, SP1ProvingKey, SP1VerifyingKey,
};
use strata_zkvm::{
ProofType, PublicValues, VerificationKey, ZkVmError, ZkVmHost, ZkVmInputBuilder, ZkVmResult,
};
Expand Down Expand Up @@ -40,7 +42,7 @@
}

pub fn init(guest_code: &[u8]) -> Self {
let client = ProverClient::new();
let client = ProverClient::from_env();
let (proving_key, verifying_key) = client.setup(guest_code);
Self {
elf: guest_code.to_vec(),
Expand Down Expand Up @@ -68,10 +70,30 @@
std::env::set_var("SP1_PROVER", "mock");
}

let client = ProverClient::new();
// Prover network
if std::env::var("SP1_PROVER").unwrap_or_default() == "network" {
let prover_client = ProverClient::builder().network().build();

let network_prover_builder = prover_client
.prove(&self.proving_key, &prover_input)
.strategy(FulfillmentStrategy::Reserved);

Check warning on line 79 in crates/zkvm/adapters/sp1/src/host.rs

View check run for this annotation

Codecov / codecov/patch

crates/zkvm/adapters/sp1/src/host.rs#L75-L79

Added lines #L75 - L79 were not covered by tests

let network_prover = match proof_type {
ProofType::Compressed => network_prover_builder.compressed(),
ProofType::Core => network_prover_builder.core(),
ProofType::Groth16 => network_prover_builder.groth16(),

Check warning on line 84 in crates/zkvm/adapters/sp1/src/host.rs

View check run for this annotation

Codecov / codecov/patch

crates/zkvm/adapters/sp1/src/host.rs#L81-L84

Added lines #L81 - L84 were not covered by tests
};

let proof_info = network_prover
.run()
.map_err(|e| ZkVmError::ProofGenerationError(e.to_string()))?;

Check warning on line 89 in crates/zkvm/adapters/sp1/src/host.rs

View check run for this annotation

Codecov / codecov/patch

crates/zkvm/adapters/sp1/src/host.rs#L87-L89

Added lines #L87 - L89 were not covered by tests

// Start proving
let mut prover = client.prove(&self.proving_key, prover_input);
return Ok(proof_info.into());

Check warning on line 91 in crates/zkvm/adapters/sp1/src/host.rs

View check run for this annotation

Codecov / codecov/patch

crates/zkvm/adapters/sp1/src/host.rs#L91

Added line #L91 was not covered by tests
}

// Local proving
let client = ProverClient::from_env();
let mut prover = client.prove(&self.proving_key, &prover_input);
prover = match proof_type {
ProofType::Compressed => prover.compressed(),
ProofType::Core => prover.core(),
Expand Down Expand Up @@ -99,7 +121,7 @@
}

fn verify_inner(&self, proof: &SP1ProofReceipt) -> ZkVmResult<()> {
let client = ProverClient::new();
let client = ProverClient::from_env();
client
.verify(proof.as_ref(), &self.verifying_key)
.map_err(|e| ZkVmError::ProofVerificationError(e.to_string()))?;
Expand All @@ -116,7 +138,7 @@

// NOTE: SP1 prover runs in release mode only; therefore run the tests on release mode only
#[cfg(test)]
#[cfg(not(debug_assertions))]
// #[cfg(not(debug_assertions))]
mod tests {

use std::{fs::File, io::Write};
Expand Down Expand Up @@ -153,7 +175,7 @@
zkvm.verify(&proof).expect("Proof verification failed");

// assert public outputs extraction from proof works
let out: u32 = SP1Host::extract_serde_public_output(&proof.public_values).expect(
let out: u32 = SP1Host::extract_serde_public_output(proof.public_values()).expect(
"Failed to extract public
outputs",
);
Expand Down Expand Up @@ -182,12 +204,17 @@
// Note: For the fixed ELF and fixed SP1 version, the vk is fixed
assert_eq!(
zkvm.verifying_key.bytes32(),
"0x00efb1120491119751e75bc55bc95b64d33f973ecf68fcf5cbff08506c5788f9"
"0x00bb534e86ded20a0b5608bae1879132a0e1c1ea324eabae095f336899a93e32"
);

// Convert the proof to SP1ProofReceipt and extract inner proof data
let sp1_proof =
SP1ProofReceipt::try_from(proof).expect("Failed to convert to SP1ProofReceipt");
let proof_data = sp1_proof.inner();

let filename = "proof-groth16.bin";
let mut file = File::create(filename).unwrap();
file.write_all(&bincode::serialize(&proof).expect("bincode serialization failed"))
file.write_all(&bincode::serialize(&proof_data).expect("bincode serialization failed"))
.unwrap();
}
}
3 changes: 1 addition & 2 deletions crates/zkvm/adapters/sp1/src/proof.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use sp1_sdk::{SP1Proof, SP1ProofWithPublicValues, SP1PublicValues, SP1Stdin};
use sp1_sdk::{SP1Proof, SP1ProofWithPublicValues, SP1PublicValues};
use strata_zkvm::{Proof, ProofReceipt, PublicValues, ZkVmProofError};

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -39,7 +39,6 @@ impl TryFrom<&ProofReceipt> for SP1ProofReceipt {
let proof_receipt = SP1ProofWithPublicValues {
proof,
public_values,
stdin: SP1Stdin::default(),
sp1_version,
};
Ok(SP1ProofReceipt(proof_receipt))
Expand Down
2 changes: 1 addition & 1 deletion crates/zkvm/adapters/sp1/src/verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ mod tests {

#[test]
fn test_groth16_verification() {
let sp1_vkey_hash = "0x00efb1120491119751e75bc55bc95b64d33f973ecf68fcf5cbff08506c5788f9";
let sp1_vkey_hash = "0x00bb534e86ded20a0b5608bae1879132a0e1c1ea324eabae095f336899a93e32";
let vk_buf32: Buf32 = sp1_vkey_hash.parse().unwrap();
let vk_hash_str = hex::encode(vk_buf32.as_bytes());
let vk_hash_str = format!("0x{}", vk_hash_str);
Expand Down
Binary file modified crates/zkvm/adapters/sp1/tests/elf/riscv32im-succinct-zkvm-elf
100644 → 100755
Binary file not shown.
Binary file modified crates/zkvm/adapters/sp1/tests/proofs/proof-groth16.bin
Binary file not shown.
4 changes: 2 additions & 2 deletions provers/perf/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ strata-test-utils.workspace = true
strata-zkvm.workspace = true
strata-zkvm-tests = { path = "../tests/", features = ["mock", "sp1"] }

sp1-prover = "3.0.0"
sp1-sdk = "3.0.0"
sp1-prover = "=4.0.0-rc.8"
sp1-sdk = "=4.0.0-rc.8"

anyhow = "1.0.83"
bincode = "1.3.3"
Expand Down
5 changes: 3 additions & 2 deletions provers/sp1/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ strata-sp1-adapter = { path = "../../crates/zkvm/adapters/sp1", features = [

[build-dependencies]
bincode.workspace = true
cargo_metadata = "0.19.1"
sha2.workspace = true
sp1-helper = "3.0.0"
sp1-sdk = "3.0.0"
sp1-helper = "=4.0.0-rc.8"
sp1-sdk = "=4.0.0-rc.8"

[features]
default = ["prover"]
Expand Down
57 changes: 54 additions & 3 deletions provers/sp1/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ use std::{
#[cfg(not(debug_assertions))]
use bincode::{deserialize, serialize};
#[cfg(not(debug_assertions))]
use cargo_metadata::MetadataCommand;
#[cfg(not(debug_assertions))]
use sha2::{Digest, Sha256};
#[cfg(not(debug_assertions))]
use sp1_helper::{build_program_with_args, BuildArgs};
#[cfg(not(debug_assertions))]
use sp1_sdk::{HashableKey, MockProver, Prover, SP1VerifyingKey};
use sp1_sdk::{HashableKey, ProverClient, SP1VerifyingKey};

// Guest program names
const EVM_EE_STF: &str = "guest-evm-ee-stf";
Expand Down Expand Up @@ -196,7 +198,7 @@ fn ensure_cache_validity(program: &str) -> Result<SP1VerifyingKey, String> {

if !is_cache_valid(&elf_hash, &paths) {
// Cache is invalid, need to generate vk and pk
let client = MockProver::new();
let client = ProverClient::from_env();
let (pk, vk) = client.setup(&elf);

fs::write(&paths[1], elf_hash)
Expand Down Expand Up @@ -240,8 +242,11 @@ fn generate_elf_contents_and_vk_hash(program: &str) -> ([u32; 8], String) {
..Default::default()
};

// Build the program
// Build the program with the specified arguments
// Note: SP1_v4's build_programs_with_args does not handle ELF migration
// Applying a temporary workaround; remove once SP1 supports ELF migration internally
build_program_with_args(program, build_args);
migrate_elf(program);

// Now, ensure cache validity
let vk = ensure_cache_validity(program)
Expand All @@ -256,3 +261,49 @@ fn generate_elf_contents_and_vk_hash(_program: &str) -> ([u32; 8], String) {
"0x0000000000000000000000000000000000000000000000000000000000000000".to_owned(),
)
}

/// Copies the compiled ELF file of the specified program to its cache directory.
#[cfg(not(debug_assertions))]
fn migrate_elf(program: &str) {
// Get the build directory from the environment
let sp1_build_dir =
PathBuf::from(env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR is not set"));

// Form the path to the program directory
let program_path = sp1_build_dir.join(program);

// Fetch metadata for this program
let metadata = MetadataCommand::new()
.manifest_path(program_path.join("Cargo.toml"))
.exec()
.expect("Failed to get metadata");

// Use the root package name as the built ELF name
let built_elf_name = metadata
.root_package()
.expect("Failed to get root package")
.name
.clone();

// Create the cache directory
let cache_dir = program_path.join("cache");
fs::create_dir_all(&cache_dir).expect("failed to create cache dir");

// Destination path: cache/program.elf
let destination_elf_path = cache_dir.join(format!("{}.elf", program));

// Source path: program/target/elf-compilation/.../release/{built_elf_name}
let built_elf_path = program_path
.join("target")
.join("elf-compilation")
.join("riscv32im-succinct-zkvm-elf")
.join("release")
.join(&built_elf_name);

eprintln!("Got the source: {:?}", built_elf_path);
eprintln!("Got the destination: {:?}", destination_elf_path);

// Copy the file
fs::copy(&built_elf_path, &destination_elf_path)
.expect("Failed to copy the built ELF file to the cache directory");
}
Loading
Loading