Skip to content

Commit

Permalink
feat: add groth16
Browse files Browse the repository at this point in the history
  • Loading branch information
mattstam committed Aug 15, 2024
1 parent 6a6c064 commit ead5a5f
Show file tree
Hide file tree
Showing 23 changed files with 834 additions and 77 deletions.
8 changes: 4 additions & 4 deletions book/developers/building-plonk-artifacts.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Building PLONK Artifacts
# Building circuit Artifacts

To build the production Plonk Bn254 artifacts from scratch, you can use the `Makefile` inside the `prover` directory.
To build the production PLONK and Groth16 Bn254 artifacts from scratch, you can use the `Makefile` inside the `prover` directory.

```shell,noplayground
cd prover
RUST_LOG=info make build-plonk-bn254
```
RUST_LOG=info make build-circuits
```
4 changes: 4 additions & 0 deletions crates/prover/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ oneshot = "0.1.8"
name = "build_plonk_bn254"
path = "scripts/build_plonk_bn254.rs"

[[bin]]
name = "build_groth16_bn254"
path = "scripts/build_groth16_bn254.rs"

[[bin]]
name = "e2e"
path = "scripts/e2e.rs"
Expand Down
11 changes: 7 additions & 4 deletions crates/prover/Makefile
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
all:
make build-plonk-bn254
make release-plonk-bn254
make build-circuits
make release-circuits

build-plonk-bn254:
build-circuits:
rm -rf build && \
mkdir -p build && \
RUSTFLAGS='-C target-cpu=native' \
cargo run -p sp1-prover --release --bin build_plonk_bn254 --features native-gnark -- \
--build-dir=./build && \
RUSTFLAGS='-C target-cpu=native' \
cargo run -p sp1-prover --release --bin build_groth16_bn254 --features native-gnark -- \
--build-dir=./build

release-plonk-bn254:
release-circuits:
@read -p "Release version (ex. v1.0.0-testnet)? " version; \
bash release.sh $$version

Expand Down
18 changes: 18 additions & 0 deletions crates/prover/scripts/build_groth16_bn254.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
use std::path::PathBuf;

use clap::Parser;
use sp1_core::utils::setup_logger;
use sp1_prover::build::build_groth16_bn254_artifacts_with_dummy;

#[derive(Parser, Debug)]
#[clap(author, version, about, long_about = None)]
struct Args {
#[clap(short, long)]
build_dir: PathBuf,
}

pub fn main() {
setup_logger();
let args = Args::parse();
build_groth16_bn254_artifacts_with_dummy(args.build_dir);
}
37 changes: 31 additions & 6 deletions crates/prover/scripts/e2e.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use sp1_prover::{
use sp1_recursion_circuit::{stark::build_wrap_circuit, witness::Witnessable};
use sp1_recursion_compiler::ir::Witness;
use sp1_recursion_core::air::RecursionPublicValues;
use sp1_recursion_gnark_ffi::Groth16Bn254Prover;
use sp1_recursion_gnark_ffi::PlonkBn254Prover;
use sp1_stark::SP1ProverOpts;
use subtle_encoding::hex;
Expand All @@ -21,6 +22,8 @@ use subtle_encoding::hex;
struct Args {
#[clap(short, long)]
build_dir: String,
#[arg(short, long, default_value = "plonk")]
system: String,
}

pub fn main() {
Expand Down Expand Up @@ -69,25 +72,47 @@ pub fn main() {
witness.write_commited_values_digest(committed_values_digest);
witness.write_vkey_hash(vkey_hash);

tracing::info!("sanity check gnark test");
tracing::info!("sanity check plonk test");
PlonkBn254Prover::test(constraints.clone(), witness.clone());

tracing::info!("sanity check gnark build");
tracing::info!("sanity check plonk build");
PlonkBn254Prover::build(constraints.clone(), witness.clone(), build_dir.clone());

tracing::info!("sanity check gnark prove");
tracing::info!("sanity check plonk prove");
let plonk_bn254_prover = PlonkBn254Prover::new();

tracing::info!("gnark prove");
tracing::info!("plonk prove");
let proof = plonk_bn254_prover.prove(witness.clone(), build_dir.clone());

tracing::info!("verify gnark proof");
tracing::info!("verify plonk proof");
plonk_bn254_prover.verify(
&proof,
&vkey_hash.as_canonical_biguint(),
&committed_values_digest.as_canonical_biguint(),
&build_dir,
);

println!("{:?}", String::from_utf8(hex::encode(proof.encoded_proof)).unwrap());
println!("plonk proof: {:?}", String::from_utf8(hex::encode(proof.encoded_proof)).unwrap());

tracing::info!("sanity check groth16 test");
Groth16Bn254Prover::test(constraints.clone(), witness.clone());

tracing::info!("sanity check groth16 build");
Groth16Bn254Prover::build(constraints.clone(), witness.clone(), build_dir.clone());

tracing::info!("sanity check groth16 prove");
let groth16_bn254_prover = Groth16Bn254Prover::new();

tracing::info!("groth16 prove");
let proof = groth16_bn254_prover.prove(witness.clone(), build_dir.clone());

tracing::info!("verify groth16 proof");
groth16_bn254_prover.verify(
&proof,
&vkey_hash.as_canonical_biguint(),
&committed_values_digest.as_canonical_biguint(),
&build_dir,
);

println!("groth16 proof: {:?}", String::from_utf8(hex::encode(proof.encoded_proof)).unwrap());
}
45 changes: 44 additions & 1 deletion crates/prover/src/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ pub use sp1_recursion_compiler::ir::Witness;
use sp1_recursion_compiler::{config::OuterConfig, constraints::Constraint};
use sp1_recursion_core::air::RecursionPublicValues;
pub use sp1_recursion_core::stark::utils::sp1_dev_mode;
use sp1_recursion_gnark_ffi::PlonkBn254Prover;
use sp1_recursion_gnark_ffi::{Groth16Bn254Prover, PlonkBn254Prover};
use sp1_stark::{SP1ProverOpts, ShardProof, StarkVerifyingKey};

use crate::{
Expand All @@ -27,11 +27,32 @@ pub fn try_build_plonk_bn254_artifacts_dev(
build_dir
}

/// Tries to build the groth16 bn254 artifacts in the current environment.
pub fn try_build_groth16_bn254_artifacts_dev(
template_vk: &StarkVerifyingKey<OuterSC>,
template_proof: &ShardProof<OuterSC>,
) -> PathBuf {
let build_dir = groth16_bn254_artifacts_dev_dir();
println!("[sp1] building groth16 bn254 artifacts in development mode");
build_groth16_bn254_artifacts(template_vk, template_proof, &build_dir);
build_dir
}

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

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

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

/// Build the plonk bn254 artifacts to the given directory for the given verification key and
/// template proof.
pub fn build_plonk_bn254_artifacts(
Expand All @@ -45,6 +66,19 @@ pub fn build_plonk_bn254_artifacts(
PlonkBn254Prover::build(constraints, witness, build_dir);
}

/// Build the groth16 bn254 artifacts to the given directory for the given verification key and template
/// proof.
pub fn build_groth16_bn254_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);
Groth16Bn254Prover::build(constraints, witness, build_dir);
}

/// Builds the plonk bn254 artifacts to the given directory.
///
/// This may take a while as it needs to first generate a dummy proof and then it needs to compile
Expand All @@ -54,6 +88,15 @@ pub fn build_plonk_bn254_artifacts_with_dummy(build_dir: impl Into<PathBuf>) {
crate::build::build_plonk_bn254_artifacts(&wrap_vk, &wrapped_proof, build_dir.into());
}

/// Builds the groth16 bn254 artifacts to the given directory.
///
/// This may take a while as it needs to first generate a dummy proof and then it needs to compile
/// the circuit.
pub fn build_groth16_bn254_artifacts_with_dummy(build_dir: impl Into<PathBuf>) {
let (wrap_vk, wrapped_proof) = dummy_proof();
crate::build::build_groth16_bn254_artifacts(&wrap_vk, &wrapped_proof, build_dir.into());
}

/// Build the verifier constraints and template witness for the circuit.
pub fn build_constraints_and_witness(
template_vk: &StarkVerifyingKey<OuterSC>,
Expand Down
3 changes: 2 additions & 1 deletion crates/prover/src/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ pub use sp1_core_machine::io::{SP1PublicValues, SP1Stdin};
use sp1_primitives::types::RecursionProgramType;
use sp1_recursion_compiler::config::InnerConfig;
use sp1_recursion_core::runtime::RecursionProgram;
pub use sp1_recursion_gnark_ffi::plonk_bn254::PlonkBn254Proof;
pub use sp1_recursion_gnark_ffi::proof::PlonkBn254Proof;
pub use sp1_recursion_program::machine::ReduceProgramType;
pub use sp1_recursion_program::machine::{
ReduceProgramType, SP1CompressMemoryLayout, SP1DeferredMemoryLayout, SP1RecursionMemoryLayout,
SP1RootMemoryLayout,
Expand Down
2 changes: 1 addition & 1 deletion crates/prover/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ use sp1_recursion_core::{
runtime::{ExecutionRecord, RecursionProgram, Runtime as RecursionRuntime},
stark::{config::BabyBearPoseidon2Outer, RecursionAir},
};
pub use sp1_recursion_gnark_ffi::plonk_bn254::PlonkBn254Proof;
use sp1_recursion_gnark_ffi::plonk_bn254::PlonkBn254Prover;
pub use sp1_recursion_gnark_ffi::proof::PlonkBn254Proof;
use sp1_recursion_program::hints::Hintable;
pub use sp1_recursion_program::machine::{
ReduceProgramType, SP1CompressMemoryLayout, SP1DeferredMemoryLayout, SP1RecursionMemoryLayout,
Expand Down
2 changes: 1 addition & 1 deletion crates/prover/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use sp1_core_machine::{
};
use sp1_primitives::poseidon2_hash;
use sp1_recursion_core::{air::RecursionPublicValues, stark::config::BabyBearPoseidon2Outer};
use sp1_recursion_gnark_ffi::plonk_bn254::PlonkBn254Proof;
use sp1_recursion_gnark_ffi::proof::PlonkBn254Proof;
use sp1_recursion_program::machine::{
SP1CompressMemoryLayout, SP1DeferredMemoryLayout, SP1RecursionMemoryLayout,
};
Expand Down
87 changes: 66 additions & 21 deletions crates/recursion/gnark-cli/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
//! A simple CLI that wraps the gnark-ffi crate. This is called using Docker in gnark-ffi when the
//! native feature is disabled.
use sp1_recursion_gnark_ffi::ffi::{
build_plonk_bn254, prove_plonk_bn254, test_plonk_bn254, verify_plonk_bn254,
use sp1_recursion_gnark_ffi::{
ffi::{
build_groth16_bn254, build_plonk_bn254, test_groth16_bn254, test_plonk_bn254,
verify_groth16_bn254, verify_plonk_bn254,
},
ProofBn254,
};

use clap::{Args, Parser, Subcommand};
Expand All @@ -17,25 +21,28 @@ struct Cli {
command: Command,
}

#[allow(clippy::enum_variant_names)]
#[derive(Debug, Subcommand)]
enum Command {
BuildPlonk(BuildArgs),
ProvePlonk(ProveArgs),
VerifyPlonk(VerifyArgs),
TestPlonk(TestArgs),
Build(BuildArgs),
Prove(ProveArgs),
Verify(VerifyArgs),
Test(TestArgs),
}

#[derive(Debug, Args)]
struct BuildArgs {
data_dir: String,
#[arg(short, long, default_value = "plonk")]
system: String,
}

#[derive(Debug, Args)]
struct ProveArgs {
data_dir: String,
witness_path: String,
output_path: String,
#[arg(short, long, default_value = "plonk")]
system: String,
}

#[derive(Debug, Args)]
Expand All @@ -45,34 +52,68 @@ struct VerifyArgs {
vkey_hash: String,
committed_values_digest: String,
output_path: String,
#[arg(short, long, default_value = "plonk")]
system: String,
}

#[derive(Debug, Args)]
struct TestArgs {
witness_json: String,
constraints_json: String,
#[arg(short, long, default_value = "plonk")]
system: String,
}

fn run_build(args: BuildArgs) {
build_plonk_bn254(&args.data_dir);
match args.system.as_str() {
"plonk" => build_plonk_bn254(&args.data_dir),
"groth16" => build_groth16_bn254(&args.data_dir),
_ => panic!("Unsupported system: {}", args.system),
}
}

fn run_prove(args: ProveArgs) {
let proof = prove_plonk_bn254(&args.data_dir, &args.witness_path);
let proof = match args.system.as_str() {
"plonk" => prove_plonk_bn254(&args.data_dir, &args.witness_path),
"groth16" => prove_groth16_bn254(&args.data_dir, &args.witness_path),
_ => panic!("Unsupported system: {}", args.system),
};
let mut file = File::create(&args.output_path).unwrap();
bincode::serialize_into(&mut file, &proof).unwrap();
}

fn prove_plonk_bn254(data_dir: &str, witness_path: &str) -> ProofBn254 {
ProofBn254::Plonk(sp1_recursion_gnark_ffi::ffi::prove_plonk_bn254(
data_dir,
witness_path,
))
}

fn prove_groth16_bn254(data_dir: &str, witness_path: &str) -> ProofBn254 {
ProofBn254::Groth16(sp1_recursion_gnark_ffi::ffi::prove_groth16_bn254(
data_dir,
witness_path,
))
}

fn run_verify(args: VerifyArgs) {
// For proof, we read the string from file since it can be large.
let file = File::open(&args.proof_path).unwrap();
let proof = read_to_string(file).unwrap();
let result = verify_plonk_bn254(
&args.data_dir,
proof.trim(),
&args.vkey_hash,
&args.committed_values_digest,
);
let result = match args.system.as_str() {
"plonk" => verify_plonk_bn254(
&args.data_dir,
proof.trim(),
&args.vkey_hash,
&args.committed_values_digest,
),
"groth16" => verify_groth16_bn254(
&args.data_dir,
proof.trim(),
&args.vkey_hash,
&args.committed_values_digest,
),
_ => panic!("Unsupported system: {}", args.system),
};
let output = match result {
Ok(_) => "OK".to_string(),
Err(e) => e,
Expand All @@ -82,16 +123,20 @@ fn run_verify(args: VerifyArgs) {
}

fn run_test(args: TestArgs) {
test_plonk_bn254(&args.witness_json, &args.constraints_json);
match args.system.as_str() {
"plonk" => test_plonk_bn254(&args.witness_json, &args.constraints_json),
"groth16" => test_groth16_bn254(&args.witness_json, &args.constraints_json),
_ => panic!("Unsupported system: {}", args.system),
}
}

fn main() {
let cli = Cli::parse();

match cli.command {
Command::BuildPlonk(args) => run_build(args),
Command::ProvePlonk(args) => run_prove(args),
Command::VerifyPlonk(args) => run_verify(args),
Command::TestPlonk(args) => run_test(args),
Command::Build(args) => run_build(args),
Command::Prove(args) => run_prove(args),
Command::Verify(args) => run_verify(args),
Command::Test(args) => run_test(args),
}
}
Loading

0 comments on commit ead5a5f

Please sign in to comment.