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

feat: auto rebuild dev artifacts in sdk #726

Merged
merged 17 commits into from
May 14, 2024
91 changes: 55 additions & 36 deletions prover/src/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,75 @@ pub use sp1_recursion_circuit::witness::Witnessable;
pub use sp1_recursion_compiler::ir::Witness;
use sp1_recursion_compiler::{config::OuterConfig, constraints::Constraint};
use sp1_recursion_core::air::RecursionPublicValues;
use sp1_recursion_core::stark::utils::sp1_dev_mode;
pub use sp1_recursion_core::stark::utils::sp1_dev_mode;
use sp1_recursion_gnark_ffi::Groth16Prover;

use crate::install::{install_groth16_artifacts, GROTH16_ARTIFACTS_COMMIT};
use crate::utils::{babybear_bytes_to_bn254, babybears_to_bn254, words_to_bytes};
use crate::{OuterSC, SP1Prover};

/// Tries to install the Groth16 artifacts if they are not already installed.
pub fn try_install_groth16_artifacts() -> PathBuf {
let build_dir = groth16_artifacts_dir();

if build_dir.exists() {
println!("[sp1] groth16 artifacts already seem to exist at {}. if you want to re-download them, delete the directory", build_dir.display());
} else {
println!(
"[sp1] groth16 artifacts for commit {} do not exist at {}. downloading...",
GROTH16_ARTIFACTS_COMMIT,
build_dir.display()
);
install_groth16_artifacts(build_dir.clone());
}
build_dir
}

/// Tries to build the Groth16 artifacts inside the development directory.
///
/// TODO: Maybe add some additional logic here to handle rebuilding the artifacts if they are
/// already built.
pub fn try_build_groth16_artifacts_dev(
template_vk: &StarkVerifyingKey<OuterSC>,
template_proof: &ShardProof<OuterSC>,
) -> PathBuf {
let build_dir = groth16_artifacts_dev_dir();
println!("[sp1] building groth16 artifacts in development mode");
build_groth16_artifacts(template_vk, template_proof, &build_dir);
build_dir
}

/// Gets the directory where the Groth16 artifacts are installed.
pub fn groth16_artifacts_dir() -> PathBuf {
dirs::home_dir()
.unwrap()
.join(".sp1")
.join("circuits")
.join("groth16")
.join(GROTH16_ARTIFACTS_COMMIT)
}

/// Gets the directory where the Groth16 artifacts are installed in development mode.
pub fn groth16_artifacts_dev_dir() -> PathBuf {
dirs::home_dir()
.unwrap()
.join(".sp1")
.join("circuits")
.join("groth16")
.join("dev")
}

/// Build the groth16 artifacts to the given directory for the given verification key and template
/// proof.
pub fn build_groth16_artifacts(
template_vk: &StarkVerifyingKey<OuterSC>,
template_proof: &ShardProof<OuterSC>,
build_dir: impl Into<PathBuf>,
) {
let build_dir = build_dir.into();
std::fs::create_dir_all(&build_dir).expect("failed to create build directory");
let (constraints, witness) = build_constraints_and_witness(template_vk, template_proof);
Groth16Prover::build(constraints, witness, build_dir.into());
Groth16Prover::build(constraints, witness, build_dir);
}

/// Builds the groth16 artifacts to the given directory.
Expand Down Expand Up @@ -88,37 +141,3 @@ pub fn dummy_proof() -> (StarkVerifyingKey<OuterSC>, ShardProof<OuterSC>) {

(prover.wrap_vk, wrapped_proof.proof)
}

/// Gets the artifacts directory for Groth16 based on the current environment variables.
///
/// - If `SP1_DEV` is enabled, we will use a smaller version of the final
/// circuit and rebuild it for every proof. This is useful for development and testing purposes, as
/// it allows us to test the end-to-end proving without having to wait for the circuit to compile or
/// download.
///
/// - Otherwise, assume this is an official release and download the artifacts from the official
/// download url.
pub fn get_groth16_artifacts_dir() -> PathBuf {
if sp1_dev_mode() {
let build_dir = dirs::home_dir()
.unwrap()
.join(".sp1")
.join("circuits")
.join("dev");
if let Err(err) = std::fs::create_dir_all(&build_dir) {
panic!(
"failed to create build directory for groth16 artifacts: {}",
err
);
}
build_dir
} else {
let build_dir = dirs::home_dir()
.unwrap()
.join(".sp1")
.join("circuits")
.join(GROTH16_ARTIFACTS_COMMIT);
install_groth16_artifacts(build_dir.clone());
build_dir
}
}
12 changes: 0 additions & 12 deletions prover/src/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,6 @@ pub const GROTH16_ARTIFACTS_COMMIT: &str = "1eee43b6";
/// This function will download the latest groth16 artifacts from the S3 bucket and extract them to
/// the directory specified by [groth16_artifacts_dir()].
pub fn install_groth16_artifacts(build_dir: PathBuf) {
// If build directory already exists, skip the download.
if build_dir.exists() {
println!("[sp1] groth16 artifacts already seem to exist at {}. if you want to re-download them, delete the directory", build_dir.display());
return;
} else {
println!(
"[sp1] groth16 artifacts for commit {} do not exist at {}. downloading...",
GROTH16_ARTIFACTS_COMMIT,
build_dir.display()
);
}

// Create the build directory.
std::fs::create_dir_all(&build_dir).expect("failed to create build directory");

Expand Down
6 changes: 3 additions & 3 deletions prover/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -627,8 +627,8 @@ mod tests {
use std::fs::File;
use std::io::{Read, Write};

use self::build::try_build_groth16_artifacts_dev;
use super::*;
use crate::build::{build_groth16_artifacts, get_groth16_artifacts_dir};

use anyhow::Result;
use p3_field::PrimeField32;
Expand Down Expand Up @@ -696,8 +696,8 @@ mod tests {
assert_eq!(vk_digest_bn254, vk.hash_bn254());

tracing::info!("generate groth16 proof");
let artifacts_dir = get_groth16_artifacts_dir();
build_groth16_artifacts(&prover.wrap_vk, &wrapped_bn254_proof.proof, &artifacts_dir);
let artifacts_dir =
try_build_groth16_artifacts_dev(&prover.wrap_vk, &wrapped_bn254_proof.proof);
let groth16_proof = prover.wrap_groth16(wrapped_bn254_proof, artifacts_dir);
println!("{:?}", groth16_proof);

Expand Down
12 changes: 8 additions & 4 deletions sdk/src/artifacts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,19 @@ use anyhow::{Context, Result};
use futures::StreamExt;
use indicatif::{ProgressBar, ProgressStyle};
use reqwest::Client;
pub use sp1_prover::build::{build_groth16_artifacts_with_dummy, get_groth16_artifacts_dir};
pub use sp1_prover::build::{build_groth16_artifacts_with_dummy, try_install_groth16_artifacts};

/// Exports the soliditiy verifier for Groth16 proofs to the specified output directory.
///
/// WARNING: This function may take some time to complete if `SP1_DEV` is enabled (which
/// is the default) as it needs to generate an end-to-end dummy proof to export the verifier.
/// WARNING: If you are on development mode, this function assumes that the Groth16 artifacts have
/// already been built.
pub fn export_solidity_groth16_verifier(output_dir: impl Into<PathBuf>) -> Result<()> {
let output_dir: PathBuf = output_dir.into();
let artifacts_dir = sp1_prover::build::get_groth16_artifacts_dir();
let artifacts_dir = if sp1_prover::build::sp1_dev_mode() {
sp1_prover::build::groth16_artifacts_dev_dir()
} else {
sp1_prover::build::try_install_groth16_artifacts()
};
let verifier_path = artifacts_dir.join("SP1Verifier.sol");

if !verifier_path.exists() {
Expand Down
14 changes: 10 additions & 4 deletions sdk/src/provers/local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,22 @@ impl Prover for LocalProver {
}

fn prove_groth16(&self, pk: &SP1ProvingKey, stdin: SP1Stdin) -> Result<SP1Groth16Proof> {
sp1_prover::build::get_groth16_artifacts_dir();

let proof = self.prover.prove_core(pk, &stdin)?;
let deferred_proofs = stdin.proofs.iter().map(|p| p.0.clone()).collect();
let public_values = proof.public_values.clone();
let reduce_proof = self.prover.compress(&pk.vk, proof, deferred_proofs)?;
let compress_proof = self.prover.shrink(reduce_proof)?;
let outer_proof = self.prover.wrap_bn254(compress_proof)?;
let artifacts_dir = sp1_prover::build::get_groth16_artifacts_dir();
let proof = self.prover.wrap_groth16(outer_proof, artifacts_dir);

let groth16_aritfacts = if sp1_prover::build::sp1_dev_mode() {
sp1_prover::build::try_build_groth16_artifacts_dev(
&self.prover.wrap_vk,
&outer_proof.proof,
)
} else {
sp1_prover::build::try_install_groth16_artifacts()
};
let proof = self.prover.wrap_groth16(outer_proof, groth16_aritfacts);
Ok(SP1ProofWithPublicValues {
proof,
stdin,
Expand Down
Loading