diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index ec110183b0..7bd88f3474 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -18,8 +18,8 @@ concurrency: cancel-in-progress: true jobs: - groth16: - name: Groth16 + plonk: + name: Plonk runs-on: runs-on,cpu=64,ram=256,family=m7i+m7a,hdd=80,image=ubuntu22-full-x64 env: CARGO_NET_GIT_FETCH_WITH_CLI: "true" @@ -35,7 +35,7 @@ jobs: with: command: test toolchain: nightly-2024-04-17 - args: --release -p sp1-sdk --features groth16 -- test_e2e_prove_groth16 --nocapture + args: --release -p sp1-sdk --features plonk_bn254 -- test_e2e_prove_plonk_bn254 --nocapture env: RUSTFLAGS: -Copt-level=3 -Cdebug-assertions -Coverflow-checks=y -Cdebuginfo=0 -C target-cpu=native RUST_BACKTRACE: 1 \ No newline at end of file diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 2dfe2485dd..093d9fcefe 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -45,7 +45,7 @@ jobs: with: command: test toolchain: nightly-2024-04-17 - args: --release --features groth16 + args: --release --features plonk_bn254 env: RUSTFLAGS: -Copt-level=3 -Cdebug-assertions -Coverflow-checks=y -Cdebuginfo=0 -C target-cpu=native RUST_BACKTRACE: 1 @@ -76,7 +76,7 @@ jobs: with: command: test toolchain: nightly-2024-04-17 - args: --release --features groth16 + args: --release --features plonk_bn254 env: RUSTFLAGS: -Copt-level=3 -Cdebug-assertions -Coverflow-checks=y -Cdebuginfo=0 -C target-cpu=native RUST_BACKTRACE: 1 diff --git a/book/SUMMARY.md b/book/SUMMARY.md index 36a380f466..91624caa07 100644 --- a/book/SUMMARY.md +++ b/book/SUMMARY.md @@ -40,4 +40,4 @@ - [Recommended Settings](./developers/recommended-settings.md) -- [Building Groth16 Artifacts](./developers/building-groth16-artifacts.md) \ No newline at end of file +- [Building Plonk Bn254 Artifacts](./developers/building-plonk-artifacts.md) \ No newline at end of file diff --git a/book/developers/building-groth16-artifacts.md b/book/developers/building-groth16-artifacts.md deleted file mode 100644 index beeb20946e..0000000000 --- a/book/developers/building-groth16-artifacts.md +++ /dev/null @@ -1,7 +0,0 @@ -# Building Groth16 Artifacts - -To build the Groth16 artifacts from scratch, you can use the `Makefile` inside the `prover` directory. - -```shell,noplayground -RUST_LOG=info make groth16 -``` \ No newline at end of file diff --git a/book/developers/building-plonk-artifacts.md b/book/developers/building-plonk-artifacts.md new file mode 100644 index 0000000000..9efd9127d0 --- /dev/null +++ b/book/developers/building-plonk-artifacts.md @@ -0,0 +1,7 @@ +# Building Plonk BN254 Artifacts + +To build the Plonk Bn254 artifacts from scratch, you can use the `Makefile` inside the `prover` directory. + +```shell,noplayground +RUST_LOG=info make plonk-bn254 +``` \ No newline at end of file diff --git a/book/developers/recommended-settings.md b/book/developers/recommended-settings.md index 3bbc6c583b..4c03948685 100644 --- a/book/developers/recommended-settings.md +++ b/book/developers/recommended-settings.md @@ -3,4 +3,4 @@ For developers contributing to the SP1 project, we recommend the following settings: - `FRI_QUERIES=1`: Makes the prover use less bits of security to generate proofs more quickly. -- `SP1_DEV=1`: This will rebuild the Groth16 artifacts everytime they are necessary. \ No newline at end of file +- `SP1_DEV=1`: This will rebuild the Plonk Bn254 artifacts everytime they are necessary. \ No newline at end of file diff --git a/book/verifying-proofs/solidity-and-evm.md b/book/verifying-proofs/solidity-and-evm.md index 978248c5e4..117ee69a19 100644 --- a/book/verifying-proofs/solidity-and-evm.md +++ b/book/verifying-proofs/solidity-and-evm.md @@ -3,25 +3,25 @@ SP1 recently added support for verifying proofs for onchain usecases. To see an end-to-end example of using SP1 for on-chain usecases, refer to the [SP1 Project Template](https://github.com/succinctlabs/sp1-project-template/tree/main). -## Generating a Groth16 Proof +## Generating a Plonk Bn254 Proof -By default, the proofs generated by SP1 are not verifiable onchain, as they are non-constant size and STARK verification on Ethereum is very expensive. To generate a proof that can be verified onchain, we use performant STARK recursion to combine SP1 shard proofs into a single STARK proof and then wrap that in a SNARK proof. Our `ProverClient` has a function for this called `prove_groth16`. Behind the scenes, this function will first generate a normal SP1 proof, then recursively combine all of them into a single proof using the STARK recursion protocol. Finally, the proof is wrapped in a SNARK proof using Groth16. +By default, the proofs generated by SP1 are not verifiable onchain, as they are non-constant size and STARK verification on Ethereum is very expensive. To generate a proof that can be verified onchain, we use performant STARK recursion to combine SP1 shard proofs into a single STARK proof and then wrap that in a SNARK proof. Our `ProverClient` has a function for this called `prove_plonk_bn254`. Behind the scenes, this function will first generate a normal SP1 proof, then recursively combine all of them into a single proof using the STARK recursion protocol. Finally, the proof is wrapped in a SNARK proof using PLONK. -**Due to the fact that Groth16 proofs require a trusted setup, the Groth16 prover is only guaranteed to work on official releases of SP1 (i.e., `v.1.0.0-testnet`).** +**Due to the fact that PLONK Bn254 proofs require a trusted setup, the PLONK Bn254 prover is only guaranteed to work on official releases of SP1.** -To use Groth16 proving & verification locally, enable the `groth16` feature flag in the sp1-sdk and ensure that Go >1.22.1 is installed. +To use PLONK proving & verification locally, enable the `plonk_bn254` feature flag in the sp1-sdk and ensure that Go >1.22.1 is installed. ```toml -sp1-sdk = { features = ["groth16"] } +sp1-sdk = { features = ["plonk_bn254"] } ``` ### Example ```rust,noplayground -{{#include ../../examples/fibonacci/script/bin/groth16.rs}} +{{#include ../../examples/fibonacci/script/bin/plonk_bn254.rs}} ``` -You can run the above script with `RUST_LOG=info cargo run --bin groth16 --release` in `examples/fibonacci/script`. +You can run the above script with `RUST_LOG=info cargo run --bin plonk_bn254 --release` in `examples/fibonacci/script`. ## Exporting the Verifier Contract @@ -41,7 +41,7 @@ use std::path::PathBuf; fn main() { let contracts_src_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../contracts/src"); - sp1_sdk::artifacts::export_solidity_groth16_verifier(contracts_src_dir) + sp1_sdk::artifacts::export_solidity_plonk_bn254_verifier(contracts_src_dir) .expect("failed to export verifier"); } ``` \ No newline at end of file diff --git a/core/src/stark/machine.rs b/core/src/stark/machine.rs index 1afff664db..871f7b8e48 100644 --- a/core/src/stark/machine.rs +++ b/core/src/stark/machine.rs @@ -258,7 +258,7 @@ impl>> StarkMachine { // Display some statistics about the workload. let stats = record.stats(); - log::info!("Shard: {:?}", stats); + log::info!("shard: {:?}", stats); // For each chip, shard the events into segments. record.shard(config) @@ -423,12 +423,12 @@ impl>> StarkMachine { let permutation_width = permutation_traces[i].width(); let total_width = trace_width + permutation_width; tracing::debug!( - "{:<11} | Main Cols = {:<5} | Perm Cols = {:<5} | Rows = {:<10} | Cells = {:<10}", - chips[i].name(), - trace_width, - permutation_width, - traces[i].0.height(), - total_width * traces[i].0.height(), + "{:<11} | Main Cols = {:<5} | Perm Cols = {:<5} | Rows = {:<10} | Cells = {:<10}", + chips[i].name(), + trace_width, + permutation_width, + traces[i].0.height(), + total_width * traces[i].0.height(), ); } diff --git a/examples/aggregation/script/Cargo.toml b/examples/aggregation/script/Cargo.toml index 2503e3e380..ae46141d2b 100644 --- a/examples/aggregation/script/Cargo.toml +++ b/examples/aggregation/script/Cargo.toml @@ -6,7 +6,7 @@ default-run = "sp1-aggregation-example-script" [dependencies] hex = "0.4.3" -sp1-sdk = { path = "../../../sdk", features = ["groth16"] } +sp1-sdk = { path = "../../../sdk", features = ["plonk_bn254"] } tracing = "0.1.40" [build-dependencies] diff --git a/examples/aggregation/script/src/main.rs b/examples/aggregation/script/src/main.rs index 7f48d90ed1..5759d64b34 100644 --- a/examples/aggregation/script/src/main.rs +++ b/examples/aggregation/script/src/main.rs @@ -11,7 +11,7 @@ const FIBONACCI_ELF: &[u8] = include_bytes!("../../programs/fibonacci/elf/riscv32im-succinct-zkvm-elf"); /// An input to the aggregation program. -/// +/// /// Consists of a proof and a verification key. struct AggregationInput { pub proof: SP1CompressedProof, @@ -93,9 +93,9 @@ fn main() { stdin.write_proof(input.proof.proof, input.vk.vk); } - // Generate the groth16 proof. + // Generate the plonk bn254 proof. client - .prove_groth16(&aggregation_pk, stdin) + .prove_plonk_bn254(&aggregation_pk, stdin) .expect("proving failed"); - }); + }); } diff --git a/examples/fibonacci/script/Cargo.toml b/examples/fibonacci/script/Cargo.toml index c8c19623f0..5d8bfb0c8b 100644 --- a/examples/fibonacci/script/Cargo.toml +++ b/examples/fibonacci/script/Cargo.toml @@ -13,8 +13,8 @@ sha2 = "0.10.8" sp1-helper = { path = "../../../helper" } [[bin]] -name = "groth16" -path = "bin/groth16.rs" +name = "plonk_bn254" +path = "bin/plonk_bn254.rs" [[bin]] name = "compressed" diff --git a/examples/fibonacci/script/bin/groth16.rs b/examples/fibonacci/script/bin/plonk_bn254.rs similarity index 90% rename from examples/fibonacci/script/bin/groth16.rs rename to examples/fibonacci/script/bin/plonk_bn254.rs index d7fb5f9486..5628b80c48 100644 --- a/examples/fibonacci/script/bin/groth16.rs +++ b/examples/fibonacci/script/bin/plonk_bn254.rs @@ -16,7 +16,7 @@ fn main() { // Generate the proof for the given program and input. let client = ProverClient::new(); let (pk, vk) = client.setup(ELF); - let mut proof = client.prove_groth16(&pk, stdin).unwrap(); + let mut proof = client.prove_plonk_bn254(&pk, stdin).unwrap(); println!("generated proof"); @@ -29,7 +29,7 @@ fn main() { // Verify proof and public values client - .verify_groth16(&proof, &vk) + .verify_plonk_bn254(&proof, &vk) .expect("verification failed"); // Save the proof. diff --git a/prover/Cargo.toml b/prover/Cargo.toml index ac438ded52..42f014de9f 100644 --- a/prover/Cargo.toml +++ b/prover/Cargo.toml @@ -45,15 +45,15 @@ num-bigint = "0.4.5" thiserror = "1.0.60" [[bin]] -name = "build_groth16" -path = "scripts/build_groth16.rs" +name = "build_plonk_bn254" +path = "scripts/build_plonk_bn254.rs" [[bin]] name = "e2e" path = "scripts/e2e.rs" [features] -default = ["groth16"] +default = ["plonk_bn254"] neon = ["sp1-core/neon"] -groth16 = ["sp1-recursion-gnark-ffi/groth16"] +plonk_bn254 = ["sp1-recursion-gnark-ffi/plonk_bn254"] diff --git a/prover/Makefile b/prover/Makefile index 249cbce283..0531e8926a 100644 --- a/prover/Makefile +++ b/prover/Makefile @@ -1,37 +1,16 @@ all: - make fibonacci-sweep - make tendermint-sweep - make fibonacci-groth16 + make build-plonk-bn254 + make release-plonk-bn254 -build-groth16: +build-plonk-bn254: mkdir -p build && \ RUSTFLAGS='-C target-cpu=native' \ - cargo run -p sp1-prover --release --bin build_groth16 -- \ + cargo run -p sp1-prover --release --bin build_plonk_bn254 -- \ --build-dir=./build -release-groth16: +release-plonk-bn254: bash release.sh test-e2e: RUSTFLAGS='-C target-cpu=native' \ - cargo test --package sp1-prover --lib --release -- tests::test_e2e --exact --show-output - -fibonacci-sweep: - mkdir -p scripts/results && \ - rm -f scripts/results/fibonacci_sweep.log && \ - RUSTFLAGS='-C target-cpu=native -C target_feature=+avx512ifma,+avx512vl' \ - RUST_LOG=info \ - cargo run --package sp1-prover --release --bin fibonacci_sweep - -tendermint-sweep: - mkdir -p scripts/results && \ - rm -f scripts/results/tendermint_sweep.log && \ - RUSTFLAGS='-C target-cpu=native -C target_feature=+avx512ifma,+avx512vl' \ - RUST_LOG=info \ - cargo run --package sp1-prover --release --bin tendermint_sweep - -fibonacci-groth16: - mkdir -p scripts/results && \ - RUSTFLAGS='-C target-cpu=native -C target_feature=+avx512ifma,+avx512vl' \ - RUST_LOG=info \ - cargo run --package sp1-prover --release --bin fibonacci_groth16 + cargo test --package sp1-prover --lib --release -- tests::test_e2e --exact --show-output \ No newline at end of file diff --git a/prover/release.sh b/prover/release.sh index 1cf390ee96..0d8601c067 100644 --- a/prover/release.sh +++ b/prover/release.sh @@ -21,7 +21,7 @@ fi # Create archive named after the commit hash ARCHIVE_NAME="${COMMIT_HASH}.tar.gz" cd $FILE_TO_UPLOAD -tar -czvf "../$ARCHIVE_NAME" . +tar --exclude='srs.bin' --exclude='srs_lagrange.bin' -czvf "../$ARCHIVE_NAME" . cd - if [ $? -ne 0 ]; then echo "Failed to create archive." diff --git a/prover/scripts/build_groth16.rs b/prover/scripts/build_plonk_bn254.rs similarity index 74% rename from prover/scripts/build_groth16.rs rename to prover/scripts/build_plonk_bn254.rs index b95771e117..66ccb229d3 100644 --- a/prover/scripts/build_groth16.rs +++ b/prover/scripts/build_plonk_bn254.rs @@ -5,7 +5,7 @@ use std::path::PathBuf; use clap::Parser; use sp1_core::utils::setup_logger; -use sp1_prover::build::build_groth16_artifacts_with_dummy; +use sp1_prover::build::build_plonk_bn254_artifacts_with_dummy; #[derive(Parser, Debug)] #[clap(author, version, about, long_about = None)] @@ -17,5 +17,5 @@ struct Args { pub fn main() { setup_logger(); let args = Args::parse(); - build_groth16_artifacts_with_dummy(args.build_dir); + build_plonk_bn254_artifacts_with_dummy(args.build_dir); } diff --git a/prover/scripts/e2e.rs b/prover/scripts/e2e.rs index dfae892795..c4833f2202 100644 --- a/prover/scripts/e2e.rs +++ b/prover/scripts/e2e.rs @@ -14,7 +14,7 @@ use sp1_recursion_circuit::stark::build_wrap_circuit; use sp1_recursion_circuit::witness::Witnessable; use sp1_recursion_compiler::ir::Witness; use sp1_recursion_core::air::RecursionPublicValues; -use sp1_recursion_gnark_ffi::Groth16Prover; +use sp1_recursion_gnark_ffi::PlonkBn254Prover; use subtle_encoding::hex; #[derive(Parser, Debug)] @@ -70,19 +70,19 @@ pub fn main() { witness.write_vkey_hash(vkey_hash); tracing::info!("sanity check gnark test"); - Groth16Prover::test(constraints.clone(), witness.clone()); + PlonkBn254Prover::test(constraints.clone(), witness.clone()); tracing::info!("sanity check gnark build"); - Groth16Prover::build(constraints.clone(), witness.clone(), build_dir.clone()); + PlonkBn254Prover::build(constraints.clone(), witness.clone(), build_dir.clone()); tracing::info!("sanity check gnark prove"); - let groth16_prover = Groth16Prover::new(); + let plonk_bn254_prover = PlonkBn254Prover::new(); tracing::info!("gnark prove"); - let proof = groth16_prover.prove(witness.clone(), build_dir.clone()); + let proof = plonk_bn254_prover.prove(witness.clone(), build_dir.clone()); tracing::info!("verify gnark proof"); - groth16_prover.verify( + plonk_bn254_prover.verify( &proof, &vkey_hash.as_canonical_biguint(), &committed_values_digest.as_canonical_biguint(), diff --git a/prover/scripts/fibonacci_groth16.rs b/prover/scripts/fibonacci_groth16.rs index 2a5fc88d8a..a17b37bb8f 100644 --- a/prover/scripts/fibonacci_groth16.rs +++ b/prover/scripts/fibonacci_groth16.rs @@ -1,4 +1,4 @@ -//! Tests end-to-end performance of wrapping a recursion proof to Groth16. +//! Tests end-to-end performance of wrapping a recursion proof to PLONK. #![feature(generic_const_exprs)] #![allow(incomplete_features)] diff --git a/prover/src/build.rs b/prover/src/build.rs index 8aad92a8d7..bd9ce31180 100644 --- a/prover/src/build.rs +++ b/prover/src/build.rs @@ -10,66 +10,69 @@ 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::Groth16Prover; +use sp1_recursion_gnark_ffi::PlonkBn254Prover; -use crate::install::{install_groth16_artifacts, GROTH16_ARTIFACTS_COMMIT}; +use crate::install::{install_plonk_bn254_artifacts, PLONK_BN254_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(); +/// Tries to install the PLONK artifacts if they are not already installed. +pub fn try_install_plonk_bn254_artifacts() -> PathBuf { + let build_dir = plonk_bn254_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()); + println!( + "[sp1] plonk bn254 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, + "[sp1] plonk bn254 artifacts for commit {} do not exist at {}. downloading...", + PLONK_BN254_ARTIFACTS_COMMIT, build_dir.display() ); - install_groth16_artifacts(build_dir.clone()); + install_plonk_bn254_artifacts(build_dir.clone()); } build_dir } -/// Tries to build the Groth16 artifacts inside the development directory. +/// Tries to build the PLONK 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( +pub fn try_build_plonk_bn254_artifacts_dev( template_vk: &StarkVerifyingKey, template_proof: &ShardProof, ) -> 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); + let build_dir = plonk_bn254_artifacts_dev_dir(); + println!("[sp1] building plonk bn254 artifacts in development mode"); + build_plonk_bn254_artifacts(template_vk, template_proof, &build_dir); build_dir } -/// Gets the directory where the Groth16 artifacts are installed. -pub fn groth16_artifacts_dir() -> PathBuf { +/// Gets the directory where the PLONK artifacts are installed. +pub fn plonk_bn254_artifacts_dir() -> PathBuf { dirs::home_dir() .unwrap() .join(".sp1") .join("circuits") - .join("groth16") - .join(GROTH16_ARTIFACTS_COMMIT) + .join("plonk_bn254") + .join(PLONK_BN254_ARTIFACTS_COMMIT) } -/// Gets the directory where the Groth16 artifacts are installed in development mode. -pub fn groth16_artifacts_dev_dir() -> PathBuf { +/// 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("groth16") + .join("plonk_bn254") .join("dev") } -/// Build the groth16 artifacts to the given directory for the given verification key and template +/// Build the plonk bn254 artifacts to the given directory for the given verification key and template /// proof. -pub fn build_groth16_artifacts( +pub fn build_plonk_bn254_artifacts( template_vk: &StarkVerifyingKey, template_proof: &ShardProof, build_dir: impl Into, @@ -77,16 +80,16 @@ pub fn build_groth16_artifacts( 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); + PlonkBn254Prover::build(constraints, witness, build_dir); } -/// Builds the groth16 artifacts to the given directory. +/// 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 /// the circuit. -pub fn build_groth16_artifacts_with_dummy(build_dir: impl Into) { +pub fn build_plonk_bn254_artifacts_with_dummy(build_dir: impl Into) { let (wrap_vk, wrapped_proof) = dummy_proof(); - crate::build::build_groth16_artifacts(&wrap_vk, &wrapped_proof, build_dir.into()); + crate::build::build_plonk_bn254_artifacts(&wrap_vk, &wrapped_proof, build_dir.into()); } /// Build the verifier constraints and template witness for the circuit. diff --git a/prover/src/install.rs b/prover/src/install.rs index bf271ce4ae..0fa5b34507 100644 --- a/prover/src/install.rs +++ b/prover/src/install.rs @@ -6,24 +6,24 @@ use reqwest::Client; use crate::utils::block_on; -/// The base URL for the S3 bucket containing the groth16 artifacts. -pub const GROTH16_ARTIFACTS_URL_BASE: &str = "https://sp1-circuits.s3-us-east-2.amazonaws.com"; +/// The base URL for the S3 bucket containing the plonk bn254 artifacts. +pub const PLONK_BN254_ARTIFACTS_URL_BASE: &str = "https://sp1-circuits.s3-us-east-2.amazonaws.com"; -/// The current version of the groth16 artifacts. -pub const GROTH16_ARTIFACTS_COMMIT: &str = "9f43e920"; +/// The current version of the plonk bn254 artifacts. +pub const PLONK_BN254_ARTIFACTS_COMMIT: &str = "d7b2513f"; -/// Install the latest groth16 artifacts. +/// Install the latest plonk bn254 artifacts. /// -/// 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) { +/// This function will download the latest plonk bn254 artifacts from the S3 bucket and extract them to +/// the directory specified by [plonk_bn254_artifacts_dir()]. +pub fn install_plonk_bn254_artifacts(build_dir: PathBuf) { // Create the build directory. std::fs::create_dir_all(&build_dir).expect("failed to create build directory"); // Download the artifacts. let download_url = format!( "{}/{}.tar.gz", - GROTH16_ARTIFACTS_URL_BASE, GROTH16_ARTIFACTS_COMMIT + PLONK_BN254_ARTIFACTS_URL_BASE, PLONK_BN254_ARTIFACTS_COMMIT ); let mut artifacts_tar_gz_file = tempfile::NamedTempFile::new().expect("failed to create tempfile"); @@ -56,14 +56,14 @@ pub fn install_groth16_artifacts(build_dir: PathBuf) { ); } -/// The directory where the groth16 artifacts will be stored based on [GROTH16_ARTIFACTS_VERSION] -/// and [GROTH16_ARTIFACTS_URL_BASE]. -pub fn install_groth16_artifacts_dir() -> PathBuf { +/// The directory where the plonk bn254 artifacts will be stored based on [PLONK_BN254_ARTIFACTS_VERSION] +/// and [PLONK_BN254_ARTIFACTS_URL_BASE]. +pub fn install_plonk_bn254_artifacts_dir() -> PathBuf { dirs::home_dir() .unwrap() .join(".sp1") .join("circuits") - .join(GROTH16_ARTIFACTS_COMMIT) + .join(PLONK_BN254_ARTIFACTS_COMMIT) } /// Download the file with a progress bar that indicates the progress. diff --git a/prover/src/lib.rs b/prover/src/lib.rs index eabd8270ef..0b0ab87f27 100644 --- a/prover/src/lib.rs +++ b/prover/src/lib.rs @@ -5,7 +5,7 @@ //! 1. Generate shard proofs which split up and prove the valid execution of a RISC-V program. //! 2. Compress shard proofs into a single shard proof. //! 3. Wrap the shard proof into a SNARK-friendly field. -//! 4. Wrap the last shard proof, proven over the SNARK-friendly field, into a Groth16/PLONK proof. +//! 4. Wrap the last shard proof, proven over the SNARK-friendly field, into a PLONK proof. #![allow(incomplete_features)] #![feature(generic_const_exprs)] @@ -20,7 +20,7 @@ pub mod verify; use std::borrow::Borrow; use std::env; -use std::path::{Path, PathBuf}; +use std::path::Path; use crate::utils::RECONSTRUCT_COMMITMENTS_ENV_VAR; use p3_baby_bear::BabyBear; @@ -52,8 +52,6 @@ use sp1_recursion_core::{ }; pub use sp1_recursion_gnark_ffi::plonk_bn254::PlonkBn254Proof; use sp1_recursion_gnark_ffi::plonk_bn254::PlonkBn254Prover; -pub use sp1_recursion_gnark_ffi::Groth16Proof; -use sp1_recursion_gnark_ffi::Groth16Prover; use sp1_recursion_program::hints::Hintable; pub use sp1_recursion_program::machine::ReduceProgramType; use sp1_recursion_program::machine::{ @@ -77,7 +75,7 @@ pub type OuterSC = BabyBearPoseidon2Outer; const REDUCE_DEGREE: usize = 3; const COMPRESS_DEGREE: usize = 9; -const WRAP_DEGREE: usize = 5; +const WRAP_DEGREE: usize = 9; pub type ReduceAir = RecursionAir; pub type CompressAir = RecursionAir; @@ -169,7 +167,7 @@ impl SP1Prover { // Get the compress program, machine, and keys. let shrink_program = SP1RootVerifier::::build(&compress_machine, &compress_vk, true); - let shrink_machine = CompressAir::machine(InnerSC::compressed()); + let shrink_machine = CompressAir::wrap_machine_dyn(InnerSC::compressed()); let (shrink_pk, shrink_vk) = shrink_machine.setup(&shrink_program); // Get the wrap program, machine, and keys. @@ -639,9 +637,13 @@ impl SP1Prover { }) } - /// Wrap the STARK proven over a SNARK-friendly field into a Groth16 proof. - #[instrument(name = "wrap_groth16", level = "info", skip_all)] - pub fn wrap_groth16(&self, proof: SP1ReduceProof, build_dir: &Path) -> Groth16Proof { + /// Wrap the STARK proven over a SNARK-friendly field into a PLONK proof. + #[instrument(name = "wrap_plonk_bn254", level = "info", skip_all)] + pub fn wrap_plonk_bn254( + &self, + proof: SP1ReduceProof, + build_dir: &Path, + ) -> PlonkBn254Proof { let vkey_digest = proof.sp1_vkey_digest_bn254(); let commited_values_digest = proof.sp1_commited_values_digest_bn254(); @@ -650,7 +652,7 @@ impl SP1Prover { witness.write_commited_values_digest(commited_values_digest); witness.write_vkey_hash(vkey_digest); - let prover = Groth16Prover::new(); + let prover = PlonkBn254Prover::new(); let proof = prover.prove(witness, build_dir.to_path_buf()); // Verify the proof. @@ -664,13 +666,6 @@ impl SP1Prover { proof } - pub fn wrap_plonk(&self, proof: ShardProof, build_dir: PathBuf) -> PlonkBn254Proof { - let mut witness = Witness::default(); - proof.write(&mut witness); - // TODO: write pv and vkey into witness - PlonkBn254Prover::prove(witness, build_dir) - } - /// Accumulate deferred proofs into a single digest. pub fn hash_deferred_proofs( prev_digest: [Val; DIGEST_SIZE], @@ -696,7 +691,7 @@ mod tests { use std::fs::File; use std::io::{Read, Write}; - use self::build::try_build_groth16_artifacts_dev; + use self::build::try_build_plonk_bn254_artifacts_dev; use super::*; use anyhow::Result; @@ -709,7 +704,7 @@ mod tests { /// pipeline. /// /// Add `FRI_QUERIES`=1 to your environment for faster execution. Should only take a few minutes - /// on a Mac M2. Note: This test always re-builds the groth16 artifacts, so setting SP1_DEV is + /// on a Mac M2. Note: This test always re-builds the plonk bn254 artifacts, so setting SP1_DEV is /// not needed. #[test] #[serial] @@ -769,13 +764,13 @@ mod tests { let vk_digest_bn254 = wrapped_bn254_proof.sp1_vkey_digest_bn254(); assert_eq!(vk_digest_bn254, vk.hash_bn254()); - tracing::info!("generate groth16 proof"); + tracing::info!("generate plonk bn254 proof"); 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); + try_build_plonk_bn254_artifacts_dev(&prover.wrap_vk, &wrapped_bn254_proof.proof); + let plonk_bn254_proof = prover.wrap_plonk_bn254(wrapped_bn254_proof, &artifacts_dir); + println!("{:?}", plonk_bn254_proof); - prover.verify_groth16(&groth16_proof, &vk, &public_values, &artifacts_dir)?; + prover.verify_plonk_bn254(&plonk_bn254_proof, &vk, &public_values, &artifacts_dir)?; Ok(()) } diff --git a/prover/src/types.rs b/prover/src/types.rs index 198dc62660..d00f021e63 100644 --- a/prover/src/types.rs +++ b/prover/src/types.rs @@ -15,7 +15,7 @@ use sp1_core::{ }; use sp1_primitives::poseidon2_hash; use sp1_recursion_core::{air::RecursionPublicValues, stark::config::BabyBearPoseidon2Outer}; -use sp1_recursion_gnark_ffi::{plonk_bn254::PlonkBn254Proof, Groth16Proof}; +use sp1_recursion_gnark_ffi::plonk_bn254::PlonkBn254Proof; use thiserror::Error; use crate::utils::words_to_bytes_be; @@ -143,10 +143,10 @@ pub type SP1CoreProof = SP1ProofWithMetadata; /// within SP1 programs. pub type SP1ReducedProof = SP1ProofWithMetadata; -/// An SP1 proof that has been wrapped into a single Groth16 proof and can be verified onchain. -pub type SP1Groth16Proof = SP1ProofWithMetadata; +/// An SP1 proof that has been wrapped into a single PLONK proof and can be verified onchain. +pub type SP1PlonkBn254Proof = SP1ProofWithMetadata; -/// An SP1 proof that has been wrapped into a single Plonk proof and can be verified onchain. +/// An SP1 proof that has been wrapped into a single PLONK proof and can be verified onchain. pub type SP1PlonkProof = SP1ProofWithMetadata; #[derive(Serialize, Deserialize, Clone)] @@ -155,7 +155,7 @@ pub struct SP1CoreProofData(pub Vec>); pub struct SP1ReducedProofData(pub ShardProof); #[derive(Serialize, Deserialize, Clone)] -pub struct SP1Groth16ProofData(pub Groth16Proof); +pub struct SP1PlonkBn254ProofData(pub PlonkBn254Proof); #[derive(Serialize, Deserialize, Clone)] pub struct SP1PlonkProofData(pub PlonkBn254Proof); diff --git a/prover/src/verify.rs b/prover/src/verify.rs index 62f12c7e9b..fedd467cfc 100644 --- a/prover/src/verify.rs +++ b/prover/src/verify.rs @@ -11,7 +11,7 @@ use sp1_core::{ utils::BabyBearPoseidon2, }; use sp1_recursion_core::{air::RecursionPublicValues, stark::config::BabyBearPoseidon2Outer}; -use sp1_recursion_gnark_ffi::{Groth16Proof, Groth16Prover}; +use sp1_recursion_gnark_ffi::{PlonkBn254Proof, PlonkBn254Prover}; use thiserror::Error; use crate::{ @@ -19,10 +19,14 @@ use crate::{ }; #[derive(Error, Debug)] -pub enum Groth16VerificationError { - #[error("the verifying key does not match the inner groth16 proof's committed verifying key")] +pub enum PlonkVerificationError { + #[error( + "the verifying key does not match the inner plonk bn254 proof's committed verifying key" + )] InvalidVerificationKey, - #[error("the public values in the sp1 proof do not match the public values in the inner groth16 proof")] + #[error( + "the public values in the sp1 proof do not match the public values in the inner plonk bn254 proof" + )] InvalidPublicValues, } @@ -212,15 +216,15 @@ impl SP1Prover { Ok(()) } - /// Verifies a Groth16 proof using the circuit artifacts in the build directory. - pub fn verify_groth16( + /// Verifies a PLONK proof using the circuit artifacts in the build directory. + pub fn verify_plonk_bn254( &self, - proof: &Groth16Proof, + proof: &PlonkBn254Proof, vk: &SP1VerifyingKey, public_values: &SP1PublicValues, build_dir: &Path, ) -> Result<()> { - let prover = Groth16Prover::new(); + let prover = PlonkBn254Prover::new(); let vkey_hash = BigUint::from_str(&proof.public_inputs[0])?; let committed_values_digest = BigUint::from_str(&proof.public_inputs[1])?; @@ -228,29 +232,29 @@ impl SP1Prover { // Verify the proof with the corresponding public inputs. prover.verify(proof, &vkey_hash, &committed_values_digest, build_dir); - verify_groth16_public_inputs(vk, public_values, &proof.public_inputs)?; + verify_plonk_bn254_public_inputs(vk, public_values, &proof.public_inputs)?; Ok(()) } } -/// Verify the vk_hash and public_values_hash in the public inputs of the Groth16Proof match the expected values. -pub fn verify_groth16_public_inputs( +/// Verify the vk_hash and public_values_hash in the public inputs of the PlonkBn254Proof match the expected values. +pub fn verify_plonk_bn254_public_inputs( vk: &SP1VerifyingKey, public_values: &SP1PublicValues, - groth16_public_inputs: &[String], + plonk_bn254_public_inputs: &[String], ) -> Result<()> { - let expected_vk_hash = BigUint::from_str(&groth16_public_inputs[0])?; - let expected_public_values_hash = BigUint::from_str(&groth16_public_inputs[1])?; + let expected_vk_hash = BigUint::from_str(&plonk_bn254_public_inputs[0])?; + let expected_public_values_hash = BigUint::from_str(&plonk_bn254_public_inputs[1])?; let vk_hash = vk.hash_bn254().as_canonical_biguint(); if vk_hash != expected_vk_hash { - return Err(Groth16VerificationError::InvalidVerificationKey.into()); + return Err(PlonkVerificationError::InvalidVerificationKey.into()); } let public_values_hash = public_values.hash(); if public_values_hash != expected_public_values_hash { - return Err(Groth16VerificationError::InvalidPublicValues.into()); + return Err(PlonkVerificationError::InvalidPublicValues.into()); } Ok(()) diff --git a/recursion/circuit/src/challenger.rs b/recursion/circuit/src/challenger.rs index 29c4e282aa..b688059dd4 100644 --- a/recursion/circuit/src/challenger.rs +++ b/recursion/circuit/src/challenger.rs @@ -162,7 +162,7 @@ mod tests { use sp1_recursion_compiler::ir::SymbolicExt; use sp1_recursion_compiler::ir::{Builder, Witness}; use sp1_recursion_core::stark::config::{outer_perm, OuterChallenger}; - use sp1_recursion_gnark_ffi::Groth16Prover; + use sp1_recursion_gnark_ffi::PlonkBn254Prover; use super::reduce_32; use super::split_32; @@ -182,7 +182,7 @@ mod tests { let mut backend = ConstraintCompiler::::default(); let constraints = backend.emit(builder.operations); - Groth16Prover::test::(constraints.clone(), Witness::default()); + PlonkBn254Prover::test::(constraints.clone(), Witness::default()); } #[test] @@ -199,7 +199,7 @@ mod tests { let mut backend = ConstraintCompiler::::default(); let constraints = backend.emit(builder.operations); - Groth16Prover::test::(constraints.clone(), Witness::default()); + PlonkBn254Prover::test::(constraints.clone(), Witness::default()); } #[test] @@ -217,7 +217,7 @@ mod tests { let mut backend = ConstraintCompiler::::default(); let constraints = backend.emit(builder.operations); - Groth16Prover::test::(constraints.clone(), Witness::default()); + PlonkBn254Prover::test::(constraints.clone(), Witness::default()); } #[test] @@ -254,7 +254,7 @@ mod tests { let mut backend = ConstraintCompiler::::default(); let constraints = backend.emit(builder.operations); - Groth16Prover::test::(constraints.clone(), Witness::default()); + PlonkBn254Prover::test::(constraints.clone(), Witness::default()); } #[test] @@ -296,6 +296,6 @@ mod tests { let mut backend = ConstraintCompiler::::default(); let constraints = backend.emit(builder.operations); - Groth16Prover::test::(constraints.clone(), Witness::default()); + PlonkBn254Prover::test::(constraints.clone(), Witness::default()); } } diff --git a/recursion/circuit/src/constraints.rs b/recursion/circuit/src/constraints.rs index 1a456cddbc..a4e3142fed 100644 --- a/recursion/circuit/src/constraints.rs +++ b/recursion/circuit/src/constraints.rs @@ -182,7 +182,7 @@ mod tests { runtime::Runtime, stark::{config::BabyBearPoseidon2Outer, RecursionAirWideDeg3}, }; - use sp1_recursion_gnark_ffi::Groth16Prover; + use sp1_recursion_gnark_ffi::PlonkBn254Prover; use crate::stark::{tests::basic_program, StarkVerifierCircuit}; @@ -359,6 +359,6 @@ mod tests { let mut backend = ConstraintCompiler::::default(); let constraints = backend.emit(builder.operations); - Groth16Prover::test::(constraints.clone(), Witness::default()); + PlonkBn254Prover::test::(constraints.clone(), Witness::default()); } } diff --git a/recursion/circuit/src/fri.rs b/recursion/circuit/src/fri.rs index 7814a7d675..151254e2c9 100644 --- a/recursion/circuit/src/fri.rs +++ b/recursion/circuit/src/fri.rs @@ -251,7 +251,7 @@ pub mod tests { outer_perm, test_fri_config, OuterChallenge, OuterChallengeMmcs, OuterChallenger, OuterCompress, OuterDft, OuterFriProof, OuterHash, OuterPcs, OuterVal, OuterValMmcs, }; - use sp1_recursion_gnark_ffi::Groth16Prover; + use sp1_recursion_gnark_ffi::PlonkBn254Prover; use super::{verify_shape_and_sample_challenges, verify_two_adic_pcs, TwoAdicPcsRoundVariable}; use crate::{ @@ -484,7 +484,7 @@ pub mod tests { let mut backend = ConstraintCompiler::::default(); let constraints = backend.emit(builder.operations); - Groth16Prover::test::(constraints.clone(), Witness::default()); + PlonkBn254Prover::test::(constraints.clone(), Witness::default()); } #[test] @@ -557,6 +557,6 @@ pub mod tests { let mut backend = ConstraintCompiler::::default(); let constraints = backend.emit(builder.operations); - Groth16Prover::test::(constraints.clone(), Witness::default()); + PlonkBn254Prover::test::(constraints.clone(), Witness::default()); } } diff --git a/recursion/circuit/src/lib.rs b/recursion/circuit/src/lib.rs index 045edc2770..717e2d4eda 100644 --- a/recursion/circuit/src/lib.rs +++ b/recursion/circuit/src/lib.rs @@ -30,7 +30,7 @@ mod tests { use sp1_recursion_compiler::ir::Ext; use sp1_recursion_compiler::ir::ExtConst; use sp1_recursion_compiler::ir::{Builder, Felt, Witness}; - use sp1_recursion_gnark_ffi::Groth16Prover; + use sp1_recursion_gnark_ffi::PlonkBn254Prover; #[test] fn test_base_babybear() { @@ -68,7 +68,7 @@ mod tests { let constraints = backend.emit(builder.operations); let witness = Witness::default(); - Groth16Prover::test::(constraints.clone(), witness); + PlonkBn254Prover::test::(constraints.clone(), witness); } #[test] @@ -123,7 +123,7 @@ mod tests { let constraints = backend.emit(builder.operations); let witness = Witness::default(); - Groth16Prover::test::(constraints.clone(), witness); + PlonkBn254Prover::test::(constraints.clone(), witness); } #[test] @@ -143,7 +143,7 @@ mod tests { witness.write_vkey_hash(vkey_hash_bn254); witness.write_commited_values_digest(commited_values_digest_bn254); - Groth16Prover::test::(constraints.clone(), witness); + PlonkBn254Prover::test::(constraints.clone(), witness); } #[test] @@ -163,7 +163,7 @@ mod tests { let mut witness = Witness::default(); witness.write_commited_values_digest(commited_values_digest_bn254); - Groth16Prover::test::(constraints.clone(), witness); + PlonkBn254Prover::test::(constraints.clone(), witness); } #[test] @@ -183,6 +183,6 @@ mod tests { let mut witness = Witness::default(); witness.write_vkey_hash(vkey_hash_bn254); - Groth16Prover::test::(constraints.clone(), witness); + PlonkBn254Prover::test::(constraints.clone(), witness); } } diff --git a/recursion/circuit/src/poseidon2.rs b/recursion/circuit/src/poseidon2.rs index 7be8ab02c1..a5a8cc1136 100644 --- a/recursion/circuit/src/poseidon2.rs +++ b/recursion/circuit/src/poseidon2.rs @@ -64,7 +64,7 @@ pub mod tests { use sp1_recursion_compiler::constraints::ConstraintCompiler; use sp1_recursion_compiler::ir::{Builder, Felt, Var, Witness}; use sp1_recursion_core::stark::config::{outer_perm, OuterCompress, OuterHash}; - use sp1_recursion_gnark_ffi::Groth16Prover; + use sp1_recursion_gnark_ffi::PlonkBn254Prover; use crate::poseidon2::Poseidon2CircuitBuilder; use crate::types::OuterDigestVariable; @@ -92,7 +92,7 @@ pub mod tests { let mut backend = ConstraintCompiler::::default(); let constraints = backend.emit(builder.operations); - Groth16Prover::test::(constraints.clone(), Witness::default()); + PlonkBn254Prover::test::(constraints.clone(), Witness::default()); } #[test] @@ -125,7 +125,7 @@ pub mod tests { let mut backend = ConstraintCompiler::::default(); let constraints = backend.emit(builder.operations); - Groth16Prover::test::(constraints.clone(), Witness::default()); + PlonkBn254Prover::test::(constraints.clone(), Witness::default()); } #[test] @@ -145,6 +145,6 @@ pub mod tests { let mut backend = ConstraintCompiler::::default(); let constraints = backend.emit(builder.operations); - Groth16Prover::test::(constraints.clone(), Witness::default()); + PlonkBn254Prover::test::(constraints.clone(), Witness::default()); } } diff --git a/recursion/circuit/src/stark.rs b/recursion/circuit/src/stark.rs index 3d4c31d1a5..9ffc85d0e8 100644 --- a/recursion/circuit/src/stark.rs +++ b/recursion/circuit/src/stark.rs @@ -22,7 +22,7 @@ use sp1_recursion_compiler::ir::{Usize, Witness}; use sp1_recursion_compiler::prelude::SymbolicVar; use sp1_recursion_core::air::RecursionPublicValues; use sp1_recursion_core::stark::config::{outer_fri_config, BabyBearPoseidon2Outer}; -use sp1_recursion_core::stark::RecursionAirSkinnyDeg7; +use sp1_recursion_core::stark::RecursionAirSkinnyDeg9; use sp1_recursion_program::commit::PolynomialSpaceVariable; use sp1_recursion_program::stark::RecursiveVerifierConstraintFolder; use sp1_recursion_program::types::QuotientDataValues; @@ -243,7 +243,7 @@ pub fn build_wrap_circuit( template_proof: ShardProof, ) -> Vec { let outer_config = OuterSC::new(); - let outer_machine = RecursionAirSkinnyDeg7::::wrap_machine(outer_config); + let outer_machine = RecursionAirSkinnyDeg9::::wrap_machine(outer_config); let mut builder = Builder::::default(); let mut challenger = MultiField32ChallengerVariable::new(&mut builder); diff --git a/recursion/circuit/src/witness.rs b/recursion/circuit/src/witness.rs index 1217748ace..19046624f2 100644 --- a/recursion/circuit/src/witness.rs +++ b/recursion/circuit/src/witness.rs @@ -336,7 +336,7 @@ mod tests { ir::{Builder, ExtConst, Witness}, }; use sp1_recursion_core::stark::config::OuterChallenge; - use sp1_recursion_gnark_ffi::Groth16Prover; + use sp1_recursion_gnark_ffi::PlonkBn254Prover; #[test] fn test_witness_simple() { @@ -364,7 +364,7 @@ mod tests { let mut backend = ConstraintCompiler::::default(); let constraints = backend.emit(builder.operations); - Groth16Prover::test::( + PlonkBn254Prover::test::( constraints, Witness { vars: vec![Bn254Fr::one(), Bn254Fr::two()], diff --git a/recursion/compiler/src/constraints/mod.rs b/recursion/compiler/src/constraints/mod.rs index 4ac11438ac..c5c67647a9 100644 --- a/recursion/compiler/src/constraints/mod.rs +++ b/recursion/compiler/src/constraints/mod.rs @@ -1,4 +1,3 @@ -// pub mod groth16_ffi; pub mod opcodes; use core::fmt::Debug; diff --git a/recursion/core/src/cpu/air/alu.rs b/recursion/core/src/cpu/air/alu.rs index 61c34e91c3..377fc4fe82 100644 --- a/recursion/core/src/cpu/air/alu.rs +++ b/recursion/core/src/cpu/air/alu.rs @@ -8,7 +8,7 @@ use crate::{ memory::MemoryCols, }; -impl CpuChip { +impl CpuChip { /// Eval the ALU instructions. pub fn eval_alu(&self, builder: &mut AB, local: &CpuCols) where diff --git a/recursion/core/src/cpu/air/branch.rs b/recursion/core/src/cpu/air/branch.rs index d97e6653e5..91bebfa65e 100644 --- a/recursion/core/src/cpu/air/branch.rs +++ b/recursion/core/src/cpu/air/branch.rs @@ -8,7 +8,7 @@ use crate::{ memory::MemoryCols, }; -impl CpuChip { +impl CpuChip { /// Eval the BRANCH operations. pub fn eval_branch( &self, diff --git a/recursion/core/src/cpu/air/heap.rs b/recursion/core/src/cpu/air/heap.rs index 4ec656a89e..170f3246f9 100644 --- a/recursion/core/src/cpu/air/heap.rs +++ b/recursion/core/src/cpu/air/heap.rs @@ -7,7 +7,7 @@ use crate::{ runtime::HEAP_START_ADDRESS, }; -impl CpuChip { +impl CpuChip { /// Eval the heap ptr. ///s /// This function will ensure that the heap size never goes above 2^28. diff --git a/recursion/core/src/cpu/air/jump.rs b/recursion/core/src/cpu/air/jump.rs index 7accec831f..bf86a70cce 100644 --- a/recursion/core/src/cpu/air/jump.rs +++ b/recursion/core/src/cpu/air/jump.rs @@ -8,7 +8,7 @@ use crate::{ runtime::STACK_SIZE, }; -impl CpuChip { +impl CpuChip { /// Eval the JUMP instructions. /// /// This method will verify the fp column values and add to the `next_pc` expression. diff --git a/recursion/core/src/cpu/air/memory.rs b/recursion/core/src/cpu/air/memory.rs index fa3085fe5f..c0a3a2b639 100644 --- a/recursion/core/src/cpu/air/memory.rs +++ b/recursion/core/src/cpu/air/memory.rs @@ -8,7 +8,7 @@ use crate::{ memory::MemoryCols, }; -impl CpuChip { +impl CpuChip { // Eval the MEMORY instructions. pub fn eval_memory(&self, builder: &mut AB, local: &CpuCols) where diff --git a/recursion/core/src/cpu/air/mod.rs b/recursion/core/src/cpu/air/mod.rs index a817ea2886..28343367c8 100644 --- a/recursion/core/src/cpu/air/mod.rs +++ b/recursion/core/src/cpu/air/mod.rs @@ -20,7 +20,7 @@ use crate::{ memory::MemoryCols, }; -impl Air for CpuChip +impl Air for CpuChip where AB: SP1RecursionAirBuilder, { @@ -95,10 +95,17 @@ where // Constrain the is_real_flag. self.eval_is_real(builder, local, next); + + // Create a dummy constraint of the given degree to compress the permutation columns. + let mut expr = local.is_real * local.is_real; + for _ in 0..(L - 2) { + expr *= local.is_real.into(); + } + builder.assert_eq(expr.clone(), expr.clone()); } } -impl CpuChip { +impl CpuChip { /// Eval the clk. /// /// For all instructions except for FRI fold, the next clk is the current clk + 4. diff --git a/recursion/core/src/cpu/air/operands.rs b/recursion/core/src/cpu/air/operands.rs index 9b45abb02b..e67cea6dd1 100644 --- a/recursion/core/src/cpu/air/operands.rs +++ b/recursion/core/src/cpu/air/operands.rs @@ -7,7 +7,7 @@ use crate::{ memory::MemoryCols, }; -impl CpuChip { +impl CpuChip { /// Eval the operands. pub fn eval_operands(&self, builder: &mut AB, local: &CpuCols) where diff --git a/recursion/core/src/cpu/air/public_values.rs b/recursion/core/src/cpu/air/public_values.rs index 4f1a9c924c..15a23828f9 100644 --- a/recursion/core/src/cpu/air/public_values.rs +++ b/recursion/core/src/cpu/air/public_values.rs @@ -8,7 +8,7 @@ use crate::{ runtime::DIGEST_SIZE, }; -impl CpuChip { +impl CpuChip { /// Eval the COMMIT instructions. /// /// This method will verify the committed public value. diff --git a/recursion/core/src/cpu/air/system.rs b/recursion/core/src/cpu/air/system.rs index f7809ffdec..db20bf201e 100644 --- a/recursion/core/src/cpu/air/system.rs +++ b/recursion/core/src/cpu/air/system.rs @@ -7,7 +7,7 @@ use crate::{ cpu::{CpuChip, CpuCols}, }; -impl CpuChip { +impl CpuChip { /// Eval the system instructions (TRAP, HALT). pub fn eval_system_instructions( &self, diff --git a/recursion/core/src/cpu/columns/mod.rs b/recursion/core/src/cpu/columns/mod.rs index c5b863a202..5655a9661a 100644 --- a/recursion/core/src/cpu/columns/mod.rs +++ b/recursion/core/src/cpu/columns/mod.rs @@ -30,7 +30,7 @@ const fn make_col_map() -> CpuCols { pub(crate) const CPU_COL_MAP: CpuCols = make_col_map(); -impl BaseAir for CpuChip { +impl BaseAir for CpuChip { fn width(&self) -> usize { NUM_CPU_COLS } diff --git a/recursion/core/src/cpu/mod.rs b/recursion/core/src/cpu/mod.rs index 17a5d296e3..2b866b7819 100644 --- a/recursion/core/src/cpu/mod.rs +++ b/recursion/core/src/cpu/mod.rs @@ -23,7 +23,7 @@ pub struct CpuEvent { } #[derive(Default)] -pub struct CpuChip { +pub struct CpuChip { pub fixed_log2_rows: Option, pub _phantom: std::marker::PhantomData, } diff --git a/recursion/core/src/cpu/trace.rs b/recursion/core/src/cpu/trace.rs index 4ee78b9e42..c07a355d04 100644 --- a/recursion/core/src/cpu/trace.rs +++ b/recursion/core/src/cpu/trace.rs @@ -19,7 +19,7 @@ use crate::{ use super::{CpuChip, CpuCols, CPU_COL_MAP, NUM_CPU_COLS}; -impl> MachineAir for CpuChip { +impl, const L: usize> MachineAir for CpuChip { type Record = ExecutionRecord; type Program = RecursionProgram; diff --git a/recursion/core/src/multi/mod.rs b/recursion/core/src/multi/mod.rs index f0acb982ce..cbef76bc41 100644 --- a/recursion/core/src/multi/mod.rs +++ b/recursion/core/src/multi/mod.rs @@ -125,6 +125,13 @@ where let local: &MultiCols = (*local).borrow(); let next: &MultiCols = (*next).borrow(); + // Add some dummy constraints to compress the interactions. + let mut expr = local.is_fri_fold * local.is_fri_fold; + for _ in 0..(DEGREE - 2) { + expr *= local.is_fri_fold.into(); + } + builder.assert_eq(expr.clone(), expr.clone()); + let next_is_real = next.is_fri_fold + next.is_poseidon2; let local_is_real = local.is_fri_fold + local.is_poseidon2; diff --git a/recursion/core/src/poseidon2/columns.rs b/recursion/core/src/poseidon2/columns.rs index 9322c5d809..12fa730477 100644 --- a/recursion/core/src/poseidon2/columns.rs +++ b/recursion/core/src/poseidon2/columns.rs @@ -45,7 +45,6 @@ impl RoundSpecificCols { pub struct ComputationCols { pub input: [T; WIDTH], pub add_rc: [T; WIDTH], - pub sbox_deg_3: [T; WIDTH], pub sbox_deg_7: [T; WIDTH], pub output: [T; WIDTH], } diff --git a/recursion/core/src/poseidon2/external.rs b/recursion/core/src/poseidon2/external.rs index 33bd225f57..d41c5f800b 100644 --- a/recursion/core/src/poseidon2/external.rs +++ b/recursion/core/src/poseidon2/external.rs @@ -196,12 +196,7 @@ impl Poseidon2Chip { let sbox_deg_3 = computation_cols.add_rc[i] * computation_cols.add_rc[i] * computation_cols.add_rc[i]; - builder - .when(is_initial.clone() + is_external_layer.clone() + is_internal_layer.clone()) - .assert_eq(sbox_deg_3, computation_cols.sbox_deg_3[i]); - let sbox_deg_7 = computation_cols.sbox_deg_3[i] - * computation_cols.sbox_deg_3[i] - * computation_cols.add_rc[i]; + let sbox_deg_7 = sbox_deg_3.clone() * sbox_deg_3.clone() * computation_cols.add_rc[i]; builder .when(is_initial.clone() + is_external_layer.clone() + is_internal_layer.clone()) .assert_eq(sbox_deg_7, computation_cols.sbox_deg_7[i]); diff --git a/recursion/core/src/poseidon2/trace.rs b/recursion/core/src/poseidon2/trace.rs index 619c8c7743..cc6a41d94f 100644 --- a/recursion/core/src/poseidon2/trace.rs +++ b/recursion/core/src/poseidon2/trace.rs @@ -128,12 +128,11 @@ impl MachineAir for Poseidon2Chip { // Apply the sbox. for j in 0..WIDTH { - computation_cols.sbox_deg_3[j] = computation_cols.add_rc[j] + let sbox_deg_3 = computation_cols.add_rc[j] * computation_cols.add_rc[j] * computation_cols.add_rc[j]; - computation_cols.sbox_deg_7[j] = computation_cols.sbox_deg_3[j] - * computation_cols.sbox_deg_3[j] - * computation_cols.add_rc[j]; + computation_cols.sbox_deg_7[j] = + sbox_deg_3 * sbox_deg_3 * computation_cols.add_rc[j]; } // What state to use for the linear layer. diff --git a/recursion/core/src/poseidon2_wide/external.rs b/recursion/core/src/poseidon2_wide/external.rs index 5438e81be7..6fb3bc870e 100644 --- a/recursion/core/src/poseidon2_wide/external.rs +++ b/recursion/core/src/poseidon2_wide/external.rs @@ -440,6 +440,13 @@ where for r in NUM_EXTERNAL_ROUNDS / 2..NUM_EXTERNAL_ROUNDS { eval_external_round(builder, &cols, r, memory.is_real); } + + // Make the degree equivalent to WIDTH to compress the interaction columns. + let mut dummy = memory.is_real * memory.is_real; + for _ in 0..(DEGREE - 2) { + dummy *= memory.is_real.into(); + } + builder.assert_eq(dummy.clone(), dummy.clone()); } } diff --git a/recursion/core/src/stark/config.rs b/recursion/core/src/stark/config.rs index a1b3a22391..2a774ec437 100644 --- a/recursion/core/src/stark/config.rs +++ b/recursion/core/src/stark/config.rs @@ -74,11 +74,11 @@ pub fn outer_fri_config() -> FriConfig { } else { match std::env::var("FRI_QUERIES") { Ok(value) => value.parse().unwrap(), - Err(_) => 50, + Err(_) => 25, } }; FriConfig { - log_blowup: 2, + log_blowup: 4, num_queries, proof_of_work_bits: 16, mmcs: challenge_mmcs, diff --git a/recursion/core/src/stark/mod.rs b/recursion/core/src/stark/mod.rs index 7981c77ed8..540dcb613b 100644 --- a/recursion/core/src/stark/mod.rs +++ b/recursion/core/src/stark/mod.rs @@ -16,7 +16,7 @@ use std::marker::PhantomData; use crate::runtime::D; pub type RecursionAirWideDeg3 = RecursionAir; -pub type RecursionAirSkinnyDeg7 = RecursionAir; +pub type RecursionAirSkinnyDeg9 = RecursionAir; #[derive(MachineAir)] #[sp1_core_path = "sp1_core"] @@ -25,7 +25,7 @@ pub type RecursionAirSkinnyDeg7 = RecursionAir; #[builder_path = "crate::air::SP1RecursionAirBuilder"] pub enum RecursionAir, const DEGREE: usize> { Program(ProgramChip), - Cpu(CpuChip), + Cpu(CpuChip), MemoryGlobal(MemoryGlobalChip), Poseidon2Wide(Poseidon2WideChip), Poseidon2Skinny(Poseidon2Chip), @@ -53,6 +53,15 @@ impl, const DEGREE: usize> RecursionAi StarkMachine::new(config, chips, PROOF_MAX_NUM_PVS) } + /// A recursion machine with fixed trace sizes tuned to work specifically for the wrap layer. + pub fn wrap_machine_dyn>(config: SC) -> StarkMachine { + let chips = Self::get_wrap_dyn_all() + .into_iter() + .map(Chip::new) + .collect::>(); + StarkMachine::new(config, chips, PROOF_MAX_NUM_PVS) + } + pub fn get_all() -> Vec { once(RecursionAir::Program(ProgramChip)) .chain(once(RecursionAir::Cpu(CpuChip { @@ -74,14 +83,30 @@ impl, const DEGREE: usize> RecursionAi .collect() } - pub fn get_wrap_all() -> Vec { + pub fn get_wrap_dyn_all() -> Vec { once(RecursionAir::Program(ProgramChip)) .chain(once(RecursionAir::Cpu(CpuChip { - fixed_log2_rows: Some(21), + fixed_log2_rows: None, _phantom: PhantomData, }))) .chain(once(RecursionAir::MemoryGlobal(MemoryGlobalChip { + fixed_log2_rows: None, + }))) + .chain(once(RecursionAir::Multi(MultiChip { + fixed_log2_rows: None, + }))) + .chain(once(RecursionAir::RangeCheck(RangeCheckChip::default()))) + .collect() + } + + pub fn get_wrap_all() -> Vec { + once(RecursionAir::Program(ProgramChip)) + .chain(once(RecursionAir::Cpu(CpuChip { fixed_log2_rows: Some(20), + _phantom: PhantomData, + }))) + .chain(once(RecursionAir::MemoryGlobal(MemoryGlobalChip { + fixed_log2_rows: Some(19), }))) .chain(once(RecursionAir::Multi(MultiChip { fixed_log2_rows: Some(20), diff --git a/recursion/core/src/stark/utils.rs b/recursion/core/src/stark/utils.rs index 9321d82288..15c642c046 100644 --- a/recursion/core/src/stark/utils.rs +++ b/recursion/core/src/stark/utils.rs @@ -7,7 +7,7 @@ use crate::air::Block; use crate::runtime::RecursionProgram; use crate::runtime::Runtime; use crate::stark::RecursionAir; -use crate::stark::RecursionAirSkinnyDeg7; +use crate::stark::RecursionAirSkinnyDeg9; use p3_field::PrimeField32; use sp1_core::utils::run_test_machine; use std::collections::VecDeque; @@ -54,7 +54,7 @@ pub fn run_test_recursion( } if test_config == TestConfig::All || test_config == TestConfig::SkinnyDeg7 { - let machine = RecursionAirSkinnyDeg7::machine(BabyBearPoseidon2::compressed()); + let machine = RecursionAirSkinnyDeg9::machine(BabyBearPoseidon2::compressed()); let (pk, vk) = machine.setup(&program); let record = runtime.record.clone(); let result = run_test_machine(record, machine, pk, vk); @@ -64,7 +64,7 @@ pub fn run_test_recursion( } if test_config == TestConfig::All || test_config == TestConfig::SkinnyDeg7Wrap { - let machine = RecursionAirSkinnyDeg7::wrap_machine(BabyBearPoseidon2::compressed()); + let machine = RecursionAirSkinnyDeg9::wrap_machine(BabyBearPoseidon2::compressed()); let (pk, vk) = machine.setup(&program); let record = runtime.record.clone(); let result = run_test_machine(record, machine, pk, vk); @@ -77,7 +77,7 @@ pub fn run_test_recursion( /// Returns whether the `SP1_DEV` environment variable is enabled or disabled. /// /// This variable controls whether a smaller version of the circuit will be used for generating the -/// Groth16 proofs. This is useful for development and testing purposes. +/// PLONK proofs. This is useful for development and testing purposes. /// /// By default, the variable is disabled. pub fn sp1_dev_mode() -> bool { diff --git a/recursion/gnark-ffi/Cargo.toml b/recursion/gnark-ffi/Cargo.toml index d35800008a..cc3373baea 100644 --- a/recursion/gnark-ffi/Cargo.toml +++ b/recursion/gnark-ffi/Cargo.toml @@ -21,6 +21,6 @@ cc = "1.0" cfg-if = "1.0" [features] -default = ["groth16"] +default = ["plonk_bn254"] -groth16 = [] +plonk_bn254 = [] diff --git a/recursion/gnark-ffi/assets/SP1Verifier.txt b/recursion/gnark-ffi/assets/SP1Verifier.txt index ee45f9e984..a63e12c6ae 100644 --- a/recursion/gnark-ffi/assets/SP1Verifier.txt +++ b/recursion/gnark-ffi/assets/SP1Verifier.txt @@ -2,64 +2,7 @@ /// @title SP1 Verifier /// @author Succinct Labs /// @notice This contracts implements a solidity verifier for SP1. -contract SP1Verifier is Verifier { - /// @notice Deserializes a proof from the given bytes. - /// @param proofBytes The proof bytes. - function deserializeProof( - bytes memory proofBytes - ) - public - pure - returns ( - uint256[8] memory proof, - uint256[2] memory commitments, - uint256[2] memory commitmentPok - ) - { - require( - proofBytes.length == 8 * 32 + 4 + 2 * 32 + 2 * 32, - "invalid proof bytes length" - ); - - uint256 offset = 32; - for (uint256 i = 0; i < 8; i++) { - assembly { - mstore( - add(proof, add(0, mul(32, i))), - mload(add(proofBytes, add(offset, mul(32, i)))) - ) - } - } - - uint32 commitmentCount; - offset += 8 * 32; - assembly { - let dataLocation := add(proofBytes, offset) - let loadedData := mload(dataLocation) - commitmentCount := and(shr(224, loadedData), 0xFFFFFFFF) - } - - offset += 4; - for (uint256 i = 0; i < 2; i++) { - assembly { - mstore( - add(commitments, add(0, mul(32, i))), - mload(add(proofBytes, add(offset, mul(32, i)))) - ) - } - } - - offset += 2 * 32; - for (uint256 i = 0; i < 2; i++) { - assembly { - mstore( - add(commitmentPok, add(0, mul(32, i))), - mload(add(proofBytes, add(offset, mul(32, i)))) - ) - } - } - } - +contract SP1Verifier is PlonkVerifier { /// @notice Hashes the public values to a field elements inside Bn254. /// @param publicValues The public values. function hashPublicValues( @@ -77,16 +20,10 @@ contract SP1Verifier is Verifier { bytes memory publicValues, bytes memory proofBytes ) public view { - ( - uint256[8] memory proof, - uint256[2] memory commitments, - uint256[2] memory commitmentPok - ) = deserializeProof(proofBytes); bytes32 publicValuesDigest = hashPublicValues(publicValues); - uint256[2] memory inputs = [ - uint256(vkey), - uint256(publicValuesDigest) - ]; - this.verifyProof(proof, commitments, commitmentPok, inputs); + uint256[] memory inputs = new uint256[](2); + inputs[0] = uint256(vkey); + inputs[1] = uint256(publicValuesDigest); + this.Verify(proofBytes, inputs); } -} +} \ No newline at end of file diff --git a/recursion/gnark-ffi/build.rs b/recursion/gnark-ffi/build.rs index 83cfd9a158..fae3c68ed3 100644 --- a/recursion/gnark-ffi/build.rs +++ b/recursion/gnark-ffi/build.rs @@ -9,7 +9,7 @@ use bindgen::CargoCallbacks; /// Build the go library, generate Rust bindings for the exposed functions, and link the library. fn main() { cfg_if! { - if #[cfg(feature = "groth16")] { + if #[cfg(feature = "plonk_bn254")] { println!("cargo:rerun-if-changed=go"); // Define the output directory let out_dir = env::var("OUT_DIR").unwrap(); diff --git a/recursion/gnark-ffi/go/go.mod b/recursion/gnark-ffi/go/go.mod index 8cfcfd6d7e..505279b9dc 100644 --- a/recursion/gnark-ffi/go/go.mod +++ b/recursion/gnark-ffi/go/go.mod @@ -12,6 +12,7 @@ require ( github.com/bits-and-blooms/bitset v1.8.0 // indirect github.com/blang/semver/v4 v4.0.0 // indirect github.com/consensys/bavard v0.1.13 // indirect + github.com/consensys/gnark-ignition-verifier v0.0.0-20230527014722-10693546ab33 github.com/davecgh/go-spew v1.1.1 // indirect github.com/fxamacker/cbor/v2 v2.5.0 // indirect github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b // indirect diff --git a/recursion/gnark-ffi/go/go.sum b/recursion/gnark-ffi/go/go.sum index a2d96911cf..1cba1df674 100644 --- a/recursion/gnark-ffi/go/go.sum +++ b/recursion/gnark-ffi/go/go.sum @@ -8,6 +8,8 @@ github.com/consensys/gnark v0.10.1-0.20240504023521-d9bfacd7cb60 h1:+m2KO2BeqBkH github.com/consensys/gnark v0.10.1-0.20240504023521-d9bfacd7cb60/go.mod h1:DU7zXvIuOqheiS3EgVdD7ydbXDiLh71FkaArWPxwJqY= github.com/consensys/gnark-crypto v0.12.2-0.20240504013751-564b6f724c3b h1:tu0NaVr64o6vXzy9rYSK/LCZXmS+u/k9eP1F8OtRUWQ= github.com/consensys/gnark-crypto v0.12.2-0.20240504013751-564b6f724c3b/go.mod h1:wKqwsieaKPThcFkHe0d0zMsbHEUWFmZcG7KBCse210o= +github.com/consensys/gnark-ignition-verifier v0.0.0-20230527014722-10693546ab33 h1:z42ewLaLxoTYeQ17arcF4WExZc/eSaN3YVlF7eEaPt4= +github.com/consensys/gnark-ignition-verifier v0.0.0-20230527014722-10693546ab33/go.mod h1:JdKor28c/KR4BbznP88bz8AAvnCgovzrB3KWsiR7lwk= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= diff --git a/recursion/gnark-ffi/go/main.go b/recursion/gnark-ffi/go/main.go index 7e842d3d75..89bba4a7e8 100644 --- a/recursion/gnark-ffi/go/main.go +++ b/recursion/gnark-ffi/go/main.go @@ -7,7 +7,7 @@ typedef struct { char *PublicInputs[2]; char *EncodedProof; char *RawProof; -} C_Groth16Proof; +} C_PlonkBn254Proof; */ import "C" import ( @@ -17,50 +17,51 @@ import ( "sync" "github.com/consensys/gnark-crypto/ecc" - "github.com/consensys/gnark/backend/groth16" + "github.com/consensys/gnark/backend/plonk" "github.com/consensys/gnark/frontend" - "github.com/consensys/gnark/frontend/cs/r1cs" + "github.com/consensys/gnark/frontend/cs/scs" + "github.com/consensys/gnark/test/unsafekzg" "github.com/succinctlabs/sp1-recursion-gnark/sp1" ) func main() {} -//export ProveGroth16 -func ProveGroth16(dataDir *C.char, witnessPath *C.char) *C.C_Groth16Proof { +//export ProvePlonkBn254 +func ProvePlonkBn254(dataDir *C.char, witnessPath *C.char) *C.C_PlonkBn254Proof { dataDirString := C.GoString(dataDir) witnessPathString := C.GoString(witnessPath) - sp1Groth16Proof := sp1.ProveGroth16(dataDirString, witnessPathString) + sp1PlonkBn254Proof := sp1.Prove(dataDirString, witnessPathString) - ms := C.malloc(C.sizeof_C_Groth16Proof) + ms := C.malloc(C.sizeof_C_PlonkBn254Proof) if ms == nil { return nil } - structPtr := (*C.C_Groth16Proof)(ms) - structPtr.PublicInputs[0] = C.CString(sp1Groth16Proof.PublicInputs[0]) - structPtr.PublicInputs[1] = C.CString(sp1Groth16Proof.PublicInputs[1]) - structPtr.EncodedProof = C.CString(sp1Groth16Proof.EncodedProof) - structPtr.RawProof = C.CString(sp1Groth16Proof.RawProof) + structPtr := (*C.C_PlonkBn254Proof)(ms) + structPtr.PublicInputs[0] = C.CString(sp1PlonkBn254Proof.PublicInputs[0]) + structPtr.PublicInputs[1] = C.CString(sp1PlonkBn254Proof.PublicInputs[1]) + structPtr.EncodedProof = C.CString(sp1PlonkBn254Proof.EncodedProof) + structPtr.RawProof = C.CString(sp1PlonkBn254Proof.RawProof) return structPtr } -//export BuildGroth16 -func BuildGroth16(dataDir *C.char) { +//export BuildPlonkBn254 +func BuildPlonkBn254(dataDir *C.char) { // Sanity check the required arguments have been provided. dataDirString := C.GoString(dataDir) - sp1.BuildGroth16(dataDirString) + sp1.Build(dataDirString) } -//export VerifyGroth16 -func VerifyGroth16(dataDir *C.char, proof *C.char, vkeyHash *C.char, commitedValuesDigest *C.char) *C.char { +//export VerifyPlonkBn254 +func VerifyPlonkBn254(dataDir *C.char, proof *C.char, vkeyHash *C.char, commitedValuesDigest *C.char) *C.char { dataDirString := C.GoString(dataDir) proofString := C.GoString(proof) vkeyHashString := C.GoString(vkeyHash) commitedValuesDigestString := C.GoString(commitedValuesDigest) - err := sp1.VerifyGroth16(dataDirString, proofString, vkeyHashString, commitedValuesDigestString) + err := sp1.Verify(dataDirString, proofString, vkeyHashString, commitedValuesDigestString) if err != nil { return C.CString(err.Error()) } @@ -69,8 +70,8 @@ func VerifyGroth16(dataDir *C.char, proof *C.char, vkeyHash *C.char, commitedVal var testMutex = &sync.Mutex{} -//export TestGroth16 -func TestGroth16(witnessPath *C.char, constraintsJson *C.char) *C.char { +//export TestPlonkBn254 +func TestPlonkBn254(witnessPath *C.char, constraintsJson *C.char) *C.char { // Because of the global env variables used here, we need to lock this function testMutex.Lock() witnessPathString := C.GoString(witnessPath) @@ -107,16 +108,20 @@ func TestMain() error { // Compile the circuit. circuit := sp1.NewCircuit(inputs) - builder := r1cs.NewBuilder - r1cs, err := frontend.Compile(ecc.BN254.ScalarField(), builder, &circuit) + builder := scs.NewBuilder + scs, err := frontend.Compile(ecc.BN254.ScalarField(), builder, &circuit) if err != nil { return err } - fmt.Println("[sp1] groth16 verifier constraints:", r1cs.GetNbConstraints()) + fmt.Println("[sp1] gnark verifier constraints:", scs.GetNbConstraints()) // Run the dummy setup. - var pk groth16.ProvingKey - pk, err = groth16.DummySetup(r1cs) + srs, srsLagrange, err := unsafekzg.NewSRS(scs) + if err != nil { + return err + } + var pk plonk.ProvingKey + pk, _, err = plonk.Setup(scs, srs, srsLagrange) if err != nil { return err } @@ -129,7 +134,7 @@ func TestMain() error { } // Generate the proof. - _, err = groth16.Prove(r1cs, pk, witness) + _, err = plonk.Prove(scs, pk, witness) if err != nil { return err } diff --git a/recursion/gnark-ffi/go/sp1/build.go b/recursion/gnark-ffi/go/sp1/build.go index ccbfb5449d..1ea42404da 100644 --- a/recursion/gnark-ffi/go/sp1/build.go +++ b/recursion/gnark-ffi/go/sp1/build.go @@ -1,19 +1,22 @@ package sp1 import ( - "crypto/sha256" "encoding/json" + "fmt" + "log" "os" + "strings" "github.com/consensys/gnark-crypto/ecc" - "github.com/consensys/gnark/backend" - "github.com/consensys/gnark/backend/groth16" + "github.com/consensys/gnark-crypto/kzg" + "github.com/consensys/gnark/backend/plonk" "github.com/consensys/gnark/frontend" - "github.com/consensys/gnark/frontend/cs/r1cs" + "github.com/consensys/gnark/frontend/cs/scs" + "github.com/consensys/gnark/test/unsafekzg" + "github.com/succinctlabs/sp1-recursion-gnark/sp1/trusted_setup" ) -func BuildGroth16(dataDir string) { - +func Build(dataDir string) { // Set the enviroment variable for the constraints file. // // TODO: There might be some non-determinism if a single processe is running this command @@ -21,7 +24,7 @@ func BuildGroth16(dataDir string) { os.Setenv("CONSTRAINTS_JSON", dataDir+"/"+CONSTRAINTS_JSON_FILE) // Read the file. - witnessInputPath := dataDir + "/witness_groth16.json" + witnessInputPath := dataDir + "/witness.json" data, err := os.ReadFile(witnessInputPath) if err != nil { panic(err) @@ -38,13 +41,96 @@ func BuildGroth16(dataDir string) { circuit := NewCircuit(witnessInput) // Compile the circuit. - r1cs, err := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &circuit) + scs, err := frontend.Compile(ecc.BN254.ScalarField(), scs.NewBuilder, &circuit) + if err != nil { + panic(err) + } + + // Download the trusted setup. + var srs kzg.SRS = kzg.NewSRS(ecc.BN254) + var srsLagrange kzg.SRS = kzg.NewSRS(ecc.BN254) + srsFileName := dataDir + "/" + SRS_FILE + srsLagrangeFileName := dataDir + "/" + SRS_LAGRANGE_FILE + + srsLagrangeFile, err := os.Create(srsLagrangeFileName) if err != nil { + log.Fatal("error creating srs file: ", err) panic(err) } + defer srsLagrangeFile.Close() + + if !strings.Contains(dataDir, "dev") { + if _, err := os.Stat(srsFileName); os.IsNotExist(err) { + fmt.Println("downloading aztec ignition srs") + trusted_setup.DownloadAndSaveAztecIgnitionSrs(174, srsFileName) + + srsFile, err := os.Open(srsFileName) + if err != nil { + panic(err) + } + defer srsFile.Close() + + _, err = srs.ReadFrom(srsFile) + srsFile.Close() + if err != nil { + panic(err) + } + + srsLagrange = trusted_setup.ToLagrange(scs, srs) + _, err = srsLagrange.WriteTo(srsLagrangeFile) + if err != nil { + panic(err) + } + } else { + srsFile, err := os.Open(srsFileName) + if err != nil { + panic(err) + } + defer srsFile.Close() + + _, err = srs.ReadFrom(srsFile) + srsFile.Close() + if err != nil { + panic(err) + } + + srsLagrangeFile, err := os.Open(srsLagrangeFileName) + if err != nil { + panic(err) + } + defer srsLagrangeFile.Close() + + _, err = srsLagrange.ReadFrom(srsLagrangeFile) + srsLagrangeFile.Close() + if err != nil { + panic(err) + } + } + } else { + srs, srsLagrange, err = unsafekzg.NewSRS(scs) + if err != nil { + panic(err) + } + + srsFile, err := os.Create(srsFileName) + if err != nil { + panic(err) + } + defer srsFile.Close() + + _, err = srs.WriteTo(srsFile) + if err != nil { + panic(err) + } + + _, err = srsLagrange.WriteTo(srsLagrangeFile) + if err != nil { + panic(err) + } + } - // Perform the trusted setup. - pk, vk, err := groth16.Setup(r1cs) + // Generate the proving and verifying key. + pk, vk, err := plonk.Setup(scs, srs, srsLagrange) if err != nil { panic(err) } @@ -55,7 +141,7 @@ func BuildGroth16(dataDir string) { if err != nil { panic(err) } - proof, err := groth16.Prove(r1cs, pk, witness, backend.WithProverHashToFieldFunction(sha256.New())) + proof, err := plonk.Prove(scs, pk, witness) if err != nil { panic(err) } @@ -65,7 +151,7 @@ func BuildGroth16(dataDir string) { if err != nil { panic(err) } - err = groth16.Verify(proof, vk, publicWitness, backend.WithVerifierHashToFieldFunction(sha256.New())) + err = plonk.Verify(proof, vk, publicWitness) if err != nil { panic(err) } @@ -81,12 +167,12 @@ func BuildGroth16(dataDir string) { vk.ExportSolidity(solidityVerifierFile) // Write the R1CS. - r1csFile, err := os.Create(dataDir + "/" + CIRCUIT_PATH) + scsFile, err := os.Create(dataDir + "/" + CIRCUIT_PATH) if err != nil { panic(err) } - defer r1csFile.Close() - _, err = r1cs.WriteTo(r1csFile) + defer scsFile.Close() + _, err = scs.WriteTo(scsFile) if err != nil { panic(err) } @@ -108,5 +194,8 @@ func BuildGroth16(dataDir string) { panic(err) } defer pkFile.Close() - pk.WriteDump(pkFile) + _, err = pk.WriteTo(pkFile) + if err != nil { + panic(err) + } } diff --git a/recursion/gnark-ffi/go/sp1/poseidon2/poseidon2_test.go b/recursion/gnark-ffi/go/sp1/poseidon2/poseidon2_test.go index 2352169fe1..d7bf417f70 100644 --- a/recursion/gnark-ffi/go/sp1/poseidon2/poseidon2_test.go +++ b/recursion/gnark-ffi/go/sp1/poseidon2/poseidon2_test.go @@ -48,5 +48,5 @@ func TestPoseidon2(t *testing.T) { circuit = TestPoseidon2Circuit{Input: input, ExpectedOutput: expected_output} witness = TestPoseidon2Circuit{Input: input, ExpectedOutput: expected_output} - assert.ProverSucceeded(&circuit, &witness, test.WithCurves(ecc.BN254), test.WithBackends(backend.GROTH16)) + assert.ProverSucceeded(&circuit, &witness, test.WithCurves(ecc.BN254), test.WithBackends(backend.PLONK)) } diff --git a/recursion/gnark-ffi/go/sp1/prove.go b/recursion/gnark-ffi/go/sp1/prove.go index 9db841feed..c921d11435 100644 --- a/recursion/gnark-ffi/go/sp1/prove.go +++ b/recursion/gnark-ffi/go/sp1/prove.go @@ -1,17 +1,15 @@ package sp1 import ( - "crypto/sha256" "encoding/json" "os" "github.com/consensys/gnark-crypto/ecc" - "github.com/consensys/gnark/backend" - "github.com/consensys/gnark/backend/groth16" + "github.com/consensys/gnark/backend/plonk" "github.com/consensys/gnark/frontend" ) -func ProveGroth16(dataDir string, witnessPath string) Groth16Proof { +func Prove(dataDir string, witnessPath string) Proof { // Sanity check the required arguments have been provided. if dataDir == "" { panic("dataDirStr is required") @@ -19,27 +17,27 @@ func ProveGroth16(dataDir string, witnessPath string) Groth16Proof { os.Setenv("CONSTRAINTS_JSON", dataDir+"/"+CONSTRAINTS_JSON_FILE) // Read the R1CS. - r1csFile, err := os.Open(dataDir + "/" + CIRCUIT_PATH) + scsFile, err := os.Open(dataDir + "/" + CIRCUIT_PATH) if err != nil { panic(err) } - r1cs := groth16.NewCS(ecc.BN254) - r1cs.ReadFrom(r1csFile) + scs := plonk.NewCS(ecc.BN254) + scs.ReadFrom(scsFile) // Read the proving key. pkFile, err := os.Open(dataDir + "/" + PK_PATH) if err != nil { panic(err) } - pk := groth16.NewProvingKey(ecc.BN254) - pk.ReadDump(pkFile) + pk := plonk.NewProvingKey(ecc.BN254) + pk.UnsafeReadFrom(pkFile) // Read the verifier key. vkFile, err := os.Open(dataDir + "/" + VK_PATH) if err != nil { panic(err) } - vk := groth16.NewVerifyingKey(ecc.BN254) + vk := plonk.NewVerifyingKey(ecc.BN254) vk.ReadFrom(vkFile) // Read the file. @@ -67,16 +65,16 @@ func ProveGroth16(dataDir string, witnessPath string) Groth16Proof { } // Generate the proof. - proof, err := groth16.Prove(r1cs, pk, witness, backend.WithProverHashToFieldFunction(sha256.New())) + proof, err := plonk.Prove(scs, pk, witness) if err != nil { panic(err) } // Verify proof. - err = groth16.Verify(proof, vk, publicWitness, backend.WithVerifierHashToFieldFunction(sha256.New())) + err = plonk.Verify(proof, vk, publicWitness) if err != nil { panic(err) } - return NewSP1Groth16Proof(&proof, witnessInput) + return NewSP1PlonkBn254Proof(&proof, witnessInput) } diff --git a/recursion/gnark-ffi/go/sp1/sp1.go b/recursion/gnark-ffi/go/sp1/sp1.go index a2e20a1138..82c651b774 100644 --- a/recursion/gnark-ffi/go/sp1/sp1.go +++ b/recursion/gnark-ffi/go/sp1/sp1.go @@ -11,12 +11,14 @@ import ( "github.com/succinctlabs/sp1-recursion-gnark/sp1/poseidon2" ) -var CONSTRAINTS_JSON_FILE string = "constraints_groth16.json" -var WITNESS_JSON_FILE string = "witness_groth16.json" +var SRS_FILE string = "srs.bin" +var SRS_LAGRANGE_FILE string = "srs_lagrange.bin" +var CONSTRAINTS_JSON_FILE string = "constraints.json" +var WITNESS_JSON_FILE string = "witness.json" var VERIFIER_CONTRACT_PATH string = "SP1Verifier.sol" -var CIRCUIT_PATH string = "circuit_groth16.bin" -var VK_PATH string = "vk_groth16.bin" -var PK_PATH string = "pk_groth16.bin" +var CIRCUIT_PATH string = "circuit.bin" +var VK_PATH string = "vk.bin" +var PK_PATH string = "pk.bin" type Circuit struct { VkeyHash frontend.Variable `gnark:",public"` @@ -39,7 +41,7 @@ type WitnessInput struct { CommitedValuesDigest string `json:"commited_values_digest"` } -type Groth16Proof struct { +type Proof struct { PublicInputs [2]string `json:"public_inputs"` EncodedProof string `json:"encoded_proof"` RawProof string `json:"raw_proof"` diff --git a/recursion/gnark-ffi/go/sp1/trusted_setup/trusted_setup.go b/recursion/gnark-ffi/go/sp1/trusted_setup/trusted_setup.go new file mode 100644 index 0000000000..fcafee1739 --- /dev/null +++ b/recursion/gnark-ffi/go/sp1/trusted_setup/trusted_setup.go @@ -0,0 +1,170 @@ +package trusted_setup + +import ( + "log" + "os" + + stdbits "math/bits" + + "github.com/consensys/gnark-crypto/ecc/bn254" + "github.com/consensys/gnark-crypto/ecc/bn254/fr" + kzg_bn254 "github.com/consensys/gnark-crypto/ecc/bn254/kzg" + "github.com/consensys/gnark-crypto/kzg" + "github.com/consensys/gnark-ignition-verifier/ignition" + "github.com/consensys/gnark/constraint" +) + +func sanityCheck(srs *kzg_bn254.SRS) { + // we can now use the SRS to verify a proof + // create a polynomial + f := randomPolynomial(60) + + // commit the polynomial + digest, err := kzg_bn254.Commit(f, srs.Pk) + if err != nil { + log.Fatal(err) + } + + // compute opening proof at a random point + var point fr.Element + point.SetString("4321") + proof, err := kzg_bn254.Open(f, point, srs.Pk) + if err != nil { + log.Fatal(err) + } + + // verify the claimed valued + expected := eval(f, point) + if !proof.ClaimedValue.Equal(&expected) { + log.Fatal("inconsistent claimed value") + } + + // verify correct proof + err = kzg_bn254.Verify(&digest, &proof, point, srs.Vk) + if err != nil { + log.Fatal(err) + } +} + +func randomPolynomial(size int) []fr.Element { + f := make([]fr.Element, size) + for i := 0; i < size; i++ { + f[i].SetRandom() + } + return f +} + +// eval returns p(point) where p is interpreted as a polynomial +// ∑_{i= 0; i-- { + res.Mul(&res, &point).Add(&res, &p[i]) + } + return res +} + +func DownloadAndSaveAztecIgnitionSrs(startIdx int, fileName string) { + config := ignition.Config{ + BaseURL: "https://aztec-ignition.s3.amazonaws.com/", + Ceremony: "MAIN IGNITION", // "TINY_TEST_5" + CacheDir: "./data", + } + + if config.CacheDir != "" { + err := os.MkdirAll(config.CacheDir, os.ModePerm) + + if err != nil { + log.Fatal("when creating cache dir: ", err) + panic(err) + } + } + + log.Println("fetch manifest") + + manifest, err := ignition.NewManifest(config) + + if err != nil { + log.Fatal("when fetching manifest: ", err) + } + + current, next := ignition.NewContribution(manifest.NumG1Points), ignition.NewContribution(manifest.NumG1Points) + + if err := current.Get(manifest.Participants[startIdx], config); err != nil { + log.Fatal("when fetching contribution: ", err) + } + if err := next.Get(manifest.Participants[startIdx+1], config); err != nil { + log.Fatal("when fetching contribution: ", err) + } + if !next.Follows(¤t) { + log.Fatalf("contribution %d does not follow contribution %d", startIdx+1, startIdx) + } + + for i := startIdx + 2; i < len(manifest.Participants); i++ { + log.Println("processing contribution ", i+1) + current, next = next, current + if err := next.Get(manifest.Participants[i], config); err != nil { + log.Fatal("when fetching contribution ", i+1, ": ", err) + } + if !next.Follows(¤t) { + log.Fatal("contribution ", i+1, " does not follow contribution ", i, ": ", err) + } + } + + log.Println("success ✅: all contributions are valid") + + _, _, _, g2gen := bn254.Generators() + // we use the last contribution to build a kzg SRS for bn254 + srs := kzg_bn254.SRS{ + Pk: kzg_bn254.ProvingKey{ + G1: next.G1, + }, + Vk: kzg_bn254.VerifyingKey{ + G1: next.G1[0], + G2: [2]bn254.G2Affine{ + g2gen, + next.G2[0], + }, + }, + } + + // sanity check + sanityCheck(&srs) + log.Println("success ✅: kzg sanity check with SRS") + + fSRS, err := os.Create(fileName) + if err != nil { + log.Fatal("error creating srs file: ", err) + panic(err) + } + defer fSRS.Close() + + _, err = srs.WriteTo(fSRS) + if err != nil { + log.Fatal("error writing srs file: ", err) + panic(err) + } +} + +func ToLagrange(scs constraint.ConstraintSystem, canonicalSRS kzg.SRS) kzg.SRS { + var lagrangeSRS kzg.SRS + + switch srs := canonicalSRS.(type) { + case *kzg_bn254.SRS: + var err error + sizeSystem := scs.GetNbPublicVariables() + scs.GetNbConstraints() + nextPowerTwo := 1 << stdbits.Len(uint(sizeSystem)) + newSRS := &kzg_bn254.SRS{Vk: srs.Vk} + newSRS.Pk.G1, err = kzg_bn254.ToLagrangeG1(srs.Pk.G1[:nextPowerTwo]) + if err != nil { + panic(err) + } + lagrangeSRS = newSRS + default: + panic("unrecognized curve") + } + + return lagrangeSRS +} diff --git a/recursion/gnark-ffi/go/sp1/utils.go b/recursion/gnark-ffi/go/sp1/utils.go index cade74b5fe..ac898c28bb 100644 --- a/recursion/gnark-ffi/go/sp1/utils.go +++ b/recursion/gnark-ffi/go/sp1/utils.go @@ -3,52 +3,23 @@ package sp1 import ( "bytes" "encoding/hex" - "math/big" - "github.com/consensys/gnark/backend/groth16" + "github.com/consensys/gnark/backend/plonk" "github.com/consensys/gnark/frontend" "github.com/succinctlabs/sp1-recursion-gnark/sp1/babybear" ) -func NewSP1Groth16Proof(proof *groth16.Proof, witnessInput WitnessInput) Groth16Proof { +func NewSP1PlonkBn254Proof(proof *plonk.Proof, witnessInput WitnessInput) Proof { var buf bytes.Buffer (*proof).WriteRawTo(&buf) proofBytes := buf.Bytes() - fpSize := 4 * 8 - var ( - a [2]*big.Int - b [2][2]*big.Int - c [2]*big.Int - ) - a[0] = new(big.Int).SetBytes(proofBytes[fpSize*0 : fpSize*1]) - a[1] = new(big.Int).SetBytes(proofBytes[fpSize*1 : fpSize*2]) - b[0][0] = new(big.Int).SetBytes(proofBytes[fpSize*2 : fpSize*3]) - b[0][1] = new(big.Int).SetBytes(proofBytes[fpSize*3 : fpSize*4]) - b[1][0] = new(big.Int).SetBytes(proofBytes[fpSize*4 : fpSize*5]) - b[1][1] = new(big.Int).SetBytes(proofBytes[fpSize*5 : fpSize*6]) - c[0] = new(big.Int).SetBytes(proofBytes[fpSize*6 : fpSize*7]) - c[1] = new(big.Int).SetBytes(proofBytes[fpSize*7 : fpSize*8]) - - commitmentCountBigInt := new(big.Int).SetBytes(proofBytes[fpSize*8 : fpSize*8+4]) - commitmentCount := int(commitmentCountBigInt.Int64()) - - var commitments []*big.Int = make([]*big.Int, 2*commitmentCount) - var commitmentPok [2]*big.Int - - for i := 0; i < 2*commitmentCount; i++ { - commitments[i] = new(big.Int).SetBytes(proofBytes[fpSize*8+4+i*fpSize : fpSize*8+4+(i+1)*fpSize]) - } - - commitmentPok[0] = new(big.Int).SetBytes(proofBytes[fpSize*8+4+2*commitmentCount*fpSize : fpSize*8+4+2*commitmentCount*fpSize+fpSize]) - commitmentPok[1] = new(big.Int).SetBytes(proofBytes[fpSize*8+4+2*commitmentCount*fpSize+fpSize : fpSize*8+4+2*commitmentCount*fpSize+2*fpSize]) - var publicInputs [2]string publicInputs[0] = witnessInput.VkeyHash publicInputs[1] = witnessInput.CommitedValuesDigest encodedProof := hex.EncodeToString(proofBytes) - return Groth16Proof{ + return Proof{ PublicInputs: publicInputs, EncodedProof: encodedProof, RawProof: hex.EncodeToString(proofBytes), diff --git a/recursion/gnark-ffi/go/sp1/verify.go b/recursion/gnark-ffi/go/sp1/verify.go index c5ed991ff6..0d7b5f21ad 100644 --- a/recursion/gnark-ffi/go/sp1/verify.go +++ b/recursion/gnark-ffi/go/sp1/verify.go @@ -2,18 +2,16 @@ package sp1 import ( "bytes" - "crypto/sha256" "encoding/hex" "os" "github.com/consensys/gnark-crypto/ecc" - "github.com/consensys/gnark/backend" - "github.com/consensys/gnark/backend/groth16" + "github.com/consensys/gnark/backend/plonk" "github.com/consensys/gnark/frontend" "github.com/succinctlabs/sp1-recursion-gnark/sp1/babybear" ) -func VerifyGroth16(verifyCmdDataDir string, verifyCmdProof string, verifyCmdVkeyHash string, verifyCmdCommitedValuesDigest string) error { +func Verify(verifyCmdDataDir string, verifyCmdProof string, verifyCmdVkeyHash string, verifyCmdCommitedValuesDigest string) error { // Sanity check the required arguments have been provided. if verifyCmdDataDir == "" { panic("--data is required") @@ -24,7 +22,7 @@ func VerifyGroth16(verifyCmdDataDir string, verifyCmdProof string, verifyCmdVkey if err != nil { panic(err) } - proof := groth16.NewProof(ecc.BN254) + proof := plonk.NewProof(ecc.BN254) if _, err := proof.ReadFrom(bytes.NewReader(proofDecodedBytes)); err != nil { panic(err) } @@ -34,7 +32,7 @@ func VerifyGroth16(verifyCmdDataDir string, verifyCmdProof string, verifyCmdVkey if err != nil { panic(err) } - vk := groth16.NewVerifyingKey(ecc.BN254) + vk := plonk.NewVerifyingKey(ecc.BN254) vk.ReadFrom(vkFile) // Compute the public witness. @@ -55,6 +53,6 @@ func VerifyGroth16(verifyCmdDataDir string, verifyCmdProof string, verifyCmdVkey } // Verify proof. - err = groth16.Verify(proof, vk, publicWitness, backend.WithVerifierHashToFieldFunction(sha256.New())) + err = plonk.Verify(proof, vk, publicWitness) return err } diff --git a/recursion/gnark-ffi/src/ffi.rs b/recursion/gnark-ffi/src/ffi.rs index 5223d79bf4..49cbeadcb1 100644 --- a/recursion/gnark-ffi/src/ffi.rs +++ b/recursion/gnark-ffi/src/ffi.rs @@ -3,25 +3,25 @@ //! Although we cast to *mut c_char because the Go signatures can't be immutable, the Go functions //! should not modify the strings. -use crate::Groth16Proof; +use crate::PlonkBn254Proof; use cfg_if::cfg_if; use std::ffi::{c_char, CString}; #[allow(warnings, clippy::all)] mod bind { - #[cfg(feature = "groth16")] + #[cfg(feature = "plonk_bn254")] include!(concat!(env!("OUT_DIR"), "/bindings.rs")); } use bind::*; -pub fn prove_groth16(data_dir: &str, witness_path: &str) -> Groth16Proof { +pub fn prove_plonk_bn254(data_dir: &str, witness_path: &str) -> PlonkBn254Proof { cfg_if! { - if #[cfg(feature = "groth16")] { + if #[cfg(feature = "plonk_bn254")] { let data_dir = CString::new(data_dir).expect("CString::new failed"); let witness_path = CString::new(witness_path).expect("CString::new failed"); let proof = unsafe { - let proof = bind::ProveGroth16( + let proof = bind::ProvePlonkBn254( data_dir.as_ptr() as *mut c_char, witness_path.as_ptr() as *mut c_char, ); @@ -31,34 +31,34 @@ pub fn prove_groth16(data_dir: &str, witness_path: &str) -> Groth16Proof { proof.into_rust() } else { - panic!("groth16 feature not enabled"); + panic!("plonk_bn254 feature not enabled"); } } } -pub fn build_groth16(data_dir: &str) { +pub fn build_plonk_bn254(data_dir: &str) { cfg_if! { - if #[cfg(feature = "groth16")] { + if #[cfg(feature = "plonk_bn254")] { let data_dir = CString::new(data_dir).expect("CString::new failed"); unsafe { - bind::BuildGroth16(data_dir.as_ptr() as *mut c_char); + bind::BuildPlonkBn254(data_dir.as_ptr() as *mut c_char); } } else { - panic!("groth16 feature not enabled"); + panic!("plonk_bn254 feature not enabled"); } } } -pub fn verify_groth16( +pub fn verify_plonk_bn254( data_dir: &str, proof: &str, vkey_hash: &str, committed_values_digest: &str, ) -> Result<(), String> { cfg_if! { - if #[cfg(feature = "groth16")] { + if #[cfg(feature = "plonk_bn254")] { let data_dir = CString::new(data_dir).expect("CString::new failed"); let proof = CString::new(proof).expect("CString::new failed"); let vkey_hash = CString::new(vkey_hash).expect("CString::new failed"); @@ -66,7 +66,7 @@ pub fn verify_groth16( CString::new(committed_values_digest).expect("CString::new failed"); let err_ptr = unsafe { - bind::VerifyGroth16( + bind::VerifyPlonkBn254( data_dir.as_ptr() as *mut c_char, proof.as_ptr() as *mut c_char, vkey_hash.as_ptr() as *mut c_char, @@ -81,29 +81,29 @@ pub fn verify_groth16( Err(err.into_string().unwrap()) } } else { - panic!("groth16 feature not enabled"); + panic!("plonk_bn254 feature not enabled"); } } } -pub fn test_groth16(witness_json: &str, constraints_json: &str) { +pub fn test_plonk_bn254(witness_json: &str, constraints_json: &str) { cfg_if! { - if #[cfg(feature = "groth16")] { + if #[cfg(feature = "plonk_bn254")] { unsafe { let witness_json = CString::new(witness_json).expect("CString::new failed"); let build_dir = CString::new(constraints_json).expect("CString::new failed"); - let err_ptr = bind::TestGroth16( + let err_ptr = bind::TestPlonkBn254( witness_json.as_ptr() as *mut c_char, build_dir.as_ptr() as *mut c_char, ); if !err_ptr.is_null() { // Safety: The error message is returned from the go code and is guaranteed to be valid. let err = CString::from_raw(err_ptr); - panic!("TestGroth16 failed: {}", err.into_string().unwrap()); + panic!("TestPlonkBn254 failed: {}", err.into_string().unwrap()); } } } else { - panic!("groth16 feature not enabled"); + panic!("plonk_bn254 feature not enabled"); } } } @@ -121,13 +121,13 @@ unsafe fn c_char_ptr_to_string(input: *mut c_char) -> String { } } -#[cfg(feature = "groth16")] -impl C_Groth16Proof { - /// Converts a C Groth16Proof into a Rust Groth16Proof, freeing the C strings. - fn into_rust(self) -> Groth16Proof { +#[cfg(feature = "plonk_bn254")] +impl C_PlonkBn254Proof { + /// Converts a C PlonkBn254Proof into a Rust PlonkBn254Proof, freeing the C strings. + fn into_rust(self) -> PlonkBn254Proof { // Safety: The raw pointers are not used anymore after converted into Rust strings. unsafe { - Groth16Proof { + PlonkBn254Proof { public_inputs: [ c_char_ptr_to_string(self.PublicInputs[0]), c_char_ptr_to_string(self.PublicInputs[1]), diff --git a/recursion/gnark-ffi/src/groth16.rs b/recursion/gnark-ffi/src/groth16.rs deleted file mode 100644 index b83031d67c..0000000000 --- a/recursion/gnark-ffi/src/groth16.rs +++ /dev/null @@ -1,127 +0,0 @@ -use std::{ - fs::{File, OpenOptions}, - io::Write, - path::{Path, PathBuf}, -}; - -use crate::{ - ffi::{build_groth16, prove_groth16, test_groth16, verify_groth16}, - witness::GnarkWitness, -}; - -use num_bigint::BigUint; -use serde::{Deserialize, Serialize}; -use sp1_recursion_compiler::{ - constraints::Constraint, - ir::{Config, Witness}, -}; - -/// A prover that can generate proofs with the Groth16 protocol using bindings to Gnark. -#[derive(Debug, Clone)] -pub struct Groth16Prover; - -/// A zero-knowledge proof generated by the Groth16 protocol with a Base64 encoded gnark groth16 proof. -#[derive(Debug, Clone, Serialize, Deserialize, Default)] -pub struct Groth16Proof { - pub public_inputs: [String; 2], - pub encoded_proof: String, - pub raw_proof: String, -} - -impl Groth16Prover { - /// Creates a new [Groth16Prover]. - pub const fn new() -> Self { - Self - } - - /// Executes the prover in testing mode with a circuit definition and witness. - pub fn test(constraints: Vec, witness: Witness) { - let serialized = serde_json::to_string(&constraints).unwrap(); - - // Write constraints. - let mut constraints_file = tempfile::NamedTempFile::new().unwrap(); - constraints_file.write_all(serialized.as_bytes()).unwrap(); - - // Write witness. - let mut witness_file = tempfile::NamedTempFile::new().unwrap(); - let gnark_witness = GnarkWitness::new(witness); - let serialized = serde_json::to_string(&gnark_witness).unwrap(); - witness_file.write_all(serialized.as_bytes()).unwrap(); - - test_groth16( - witness_file.path().to_str().unwrap(), - constraints_file.path().to_str().unwrap(), - ); - } - - /// Builds the groth16 circuit locally. - pub fn build(constraints: Vec, witness: Witness, build_dir: PathBuf) { - let serialized = serde_json::to_string(&constraints).unwrap(); - - // Write constraints. - let constraints_path = build_dir.join("constraints_groth16.json"); - let mut file = File::create(constraints_path).unwrap(); - file.write_all(serialized.as_bytes()).unwrap(); - - // Write witness. - let witness_path = build_dir.join("witness_groth16.json"); - let gnark_witness = GnarkWitness::new(witness); - let mut file = File::create(witness_path).unwrap(); - let serialized = serde_json::to_string(&gnark_witness).unwrap(); - file.write_all(serialized.as_bytes()).unwrap(); - - build_groth16(build_dir.to_str().unwrap()); - - // Extend the built verifier with the sp1 verifier contract. - let groth16_verifier_path = build_dir.join("SP1Verifier.sol"); - - // Open the file in append mode. - let mut groth16_verifier_file = OpenOptions::new() - .append(true) - .open(groth16_verifier_path) - .expect("failed to open file"); - - // Write the string to the file - let sp1_verifier_str = include_str!("../assets/SP1Verifier.txt"); - groth16_verifier_file - .write_all(sp1_verifier_str.as_bytes()) - .expect("Failed to write to file"); - } - - /// Generates a Groth16 proof by sending a request to the Gnark server. - pub fn prove(&self, witness: Witness, build_dir: PathBuf) -> Groth16Proof { - // Write witness. - let mut witness_file = tempfile::NamedTempFile::new().unwrap(); - let gnark_witness = GnarkWitness::new(witness); - let serialized = serde_json::to_string(&gnark_witness).unwrap(); - witness_file.write_all(serialized.as_bytes()).unwrap(); - - prove_groth16( - build_dir.to_str().unwrap(), - witness_file.path().to_str().unwrap(), - ) - } - - /// Verify a Groth16 proof and verify that the supplied vkey_hash and committed_values_digest match. - pub fn verify( - &self, - proof: &Groth16Proof, - vkey_hash: &BigUint, - committed_values_digest: &BigUint, - build_dir: &Path, - ) { - verify_groth16( - build_dir.to_str().unwrap(), - &proof.raw_proof, - &vkey_hash.to_string(), - &committed_values_digest.to_string(), - ) - .expect("failed to verify proof") - } -} - -impl Default for Groth16Prover { - fn default() -> Self { - Self::new() - } -} diff --git a/recursion/gnark-ffi/src/lib.rs b/recursion/gnark-ffi/src/lib.rs index 31ea294d62..26940e863b 100644 --- a/recursion/gnark-ffi/src/lib.rs +++ b/recursion/gnark-ffi/src/lib.rs @@ -1,8 +1,7 @@ mod babybear; pub mod ffi; -pub mod groth16; pub mod plonk_bn254; pub mod witness; -pub use groth16::*; +pub use plonk_bn254::*; pub use witness::*; diff --git a/recursion/gnark-ffi/src/plonk_bn254.rs b/recursion/gnark-ffi/src/plonk_bn254.rs index 04a2799807..6b2ddf66be 100644 --- a/recursion/gnark-ffi/src/plonk_bn254.rs +++ b/recursion/gnark-ffi/src/plonk_bn254.rs @@ -1,146 +1,122 @@ use std::{ - fs::File, - io::{Read, Write}, - path::PathBuf, - process::{Command, Stdio}, + fs::{File, OpenOptions}, + io::Write, + path::{Path, PathBuf}, }; +use crate::{ + ffi::{build_plonk_bn254, prove_plonk_bn254, test_plonk_bn254, verify_plonk_bn254}, + witness::GnarkWitness, +}; + +use num_bigint::BigUint; use serde::{Deserialize, Serialize}; use sp1_recursion_compiler::{ constraints::Constraint, ir::{Config, Witness}, }; -use crate::GnarkWitness; - -/// A prover that can generate proofs with the PLONK-BN254 protocol using bindings to Gnark. +/// A prover that can generate proofs with the PLONK protocol using bindings to Gnark. +#[derive(Debug, Clone)] pub struct PlonkBn254Prover; -/// A zero-knowledge proof generated by the PLONK-BN254 protocol. +/// A zero-knowledge proof generated by the PLONK protocol with a Base64 encoded gnark PLONK proof. #[derive(Debug, Clone, Serialize, Deserialize, Default)] pub struct PlonkBn254Proof { - proof: String, - public_inputs: [String; 2], + pub public_inputs: [String; 2], + pub encoded_proof: String, + pub raw_proof: String, } impl PlonkBn254Prover { - /// Creates a new prover. - pub const fn new() -> Self { - PlonkBn254Prover + /// Creates a new [PlonkBn254Prover]. + pub fn new() -> Self { + Self } + /// Executes the prover in testing mode with a circuit definition and witness. + pub fn test(constraints: Vec, witness: Witness) { + let serialized = serde_json::to_string(&constraints).unwrap(); + + // Write constraints. + let mut constraints_file = tempfile::NamedTempFile::new().unwrap(); + constraints_file.write_all(serialized.as_bytes()).unwrap(); + + // Write witness. + let mut witness_file = tempfile::NamedTempFile::new().unwrap(); + let gnark_witness = GnarkWitness::new(witness); + let serialized = serde_json::to_string(&gnark_witness).unwrap(); + witness_file.write_all(serialized.as_bytes()).unwrap(); + + test_plonk_bn254( + witness_file.path().to_str().unwrap(), + constraints_file.path().to_str().unwrap(), + ); + } + + /// Builds the PLONK circuit locally. pub fn build(constraints: Vec, witness: Witness, build_dir: PathBuf) { let serialized = serde_json::to_string(&constraints).unwrap(); - let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); - let gnark_dir = manifest_dir.join("../gnark"); - let cwd = std::env::current_dir().unwrap(); // Write constraints. - let constraints_path = build_dir.join("constraints_plonk_bn254.json"); + let constraints_path = build_dir.join("constraints.json"); let mut file = File::create(constraints_path).unwrap(); file.write_all(serialized.as_bytes()).unwrap(); // Write witness. - let witness_path = build_dir.join("witness_plonk_bn254.json"); + let witness_path = build_dir.join("witness.json"); let gnark_witness = GnarkWitness::new(witness); let mut file = File::create(witness_path).unwrap(); let serialized = serde_json::to_string(&gnark_witness).unwrap(); file.write_all(serialized.as_bytes()).unwrap(); - // Run `make`. - let make = Command::new("make") - .current_dir(&gnark_dir) - .stderr(Stdio::inherit()) - .stdout(Stdio::inherit()) - .stdin(Stdio::inherit()) - .output() - .unwrap(); - if !make.status.success() { - panic!("failed to run make"); - } - - // Run the build script. - let result = Command::new("go") - .args([ - "run", - "main.go", - "build-plonk-bn254", - "--data", - cwd.join(build_dir).to_str().unwrap(), - ]) - .current_dir(gnark_dir) - .stderr(Stdio::inherit()) - .stdout(Stdio::inherit()) - .stdin(Stdio::inherit()) - .output() - .unwrap(); - - if !result.status.success() { - panic!("failed to run build script"); - } - } + build_plonk_bn254(build_dir.to_str().unwrap()); - pub fn prove(witness: Witness, build_dir: PathBuf) -> PlonkBn254Proof { - let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); - let gnark_dir = manifest_dir.join("../gnark"); - let cwd = std::env::current_dir().unwrap(); + // Extend the built verifier with the sp1 verifier contract. + let plonk_bn254_verifier_path = build_dir.join("SP1Verifier.sol"); + // Open the file in append mode. + let mut plonk_bn254_verifier_file = OpenOptions::new() + .append(true) + .open(plonk_bn254_verifier_path) + .expect("failed to open file"); + + // Write the string to the file + let sp1_verifier_str = include_str!("../assets/SP1Verifier.txt"); + plonk_bn254_verifier_file + .write_all(sp1_verifier_str.as_bytes()) + .expect("Failed to write to file"); + } + + /// Generates a PLONK proof by sending a request to the Gnark server. + pub fn prove(&self, witness: Witness, build_dir: PathBuf) -> PlonkBn254Proof { // Write witness. let mut witness_file = tempfile::NamedTempFile::new().unwrap(); let gnark_witness = GnarkWitness::new(witness); let serialized = serde_json::to_string(&gnark_witness).unwrap(); witness_file.write_all(serialized.as_bytes()).unwrap(); - // Run `make`. - let make = Command::new("make") - .current_dir(&gnark_dir) - .stderr(Stdio::inherit()) - .stdout(Stdio::inherit()) - .stdin(Stdio::inherit()) - .output() - .unwrap(); - if !make.status.success() { - panic!("failed to run make"); - } - - // Run the prove script. - let proof_file = tempfile::NamedTempFile::new().unwrap(); - let result = Command::new("go") - .args([ - "run", - "main.go", - "prove-plonk-bn254", - "--data", - cwd.join(build_dir).to_str().unwrap(), - "--witness", - witness_file.path().to_str().unwrap(), - "--proof", - proof_file.path().to_str().unwrap(), - ]) - .current_dir(gnark_dir) - .stderr(Stdio::inherit()) - .stdout(Stdio::inherit()) - .stdin(Stdio::inherit()) - .output() - .unwrap(); - - if !result.status.success() { - panic!("failed to run build script"); - } - - // Read the contents back from the tempfile. - let mut buffer = String::new(); - proof_file - .reopen() - .unwrap() - .read_to_string(&mut buffer) - .unwrap(); - - // Deserialize the JSON string back to a Groth16Proof instance - let deserialized: PlonkBn254Proof = - serde_json::from_str(&buffer).expect("Error deserializing the proof"); - - deserialized + prove_plonk_bn254( + build_dir.to_str().unwrap(), + witness_file.path().to_str().unwrap(), + ) + } + + /// Verify a PLONK proof and verify that the supplied vkey_hash and committed_values_digest match. + pub fn verify( + &self, + proof: &PlonkBn254Proof, + vkey_hash: &BigUint, + committed_values_digest: &BigUint, + build_dir: &Path, + ) { + verify_plonk_bn254( + build_dir.to_str().unwrap(), + &proof.raw_proof, + &vkey_hash.to_string(), + &committed_values_digest.to_string(), + ) + .expect("failed to verify proof") } } diff --git a/sdk/Cargo.toml b/sdk/Cargo.toml index e7f05c1fc7..2ca7450f61 100644 --- a/sdk/Cargo.toml +++ b/sdk/Cargo.toml @@ -41,7 +41,7 @@ cfg-if = "1.0" [features] neon = ["sp1-core/neon"] -groth16 = ["sp1-prover/groth16"] +plonk_bn254= ["sp1-prover/plonk_bn254"] [build-dependencies] vergen = { version = "8", default-features = false, features = [ diff --git a/sdk/src/artifacts.rs b/sdk/src/artifacts.rs index 52f1c97376..059f79a404 100644 --- a/sdk/src/artifacts.rs +++ b/sdk/src/artifacts.rs @@ -4,18 +4,20 @@ use anyhow::{Context, Result}; use futures::StreamExt; use indicatif::{ProgressBar, ProgressStyle}; use reqwest::Client; -pub use sp1_prover::build::{build_groth16_artifacts_with_dummy, try_install_groth16_artifacts}; +pub use sp1_prover::build::{ + build_plonk_bn254_artifacts_with_dummy, try_install_plonk_bn254_artifacts, +}; -/// Exports the soliditiy verifier for Groth16 proofs to the specified output directory. +/// Exports the soliditiy verifier for PLONK proofs to the specified output directory. /// -/// WARNING: If you are on development mode, this function assumes that the Groth16 artifacts have +/// WARNING: If you are on development mode, this function assumes that the PLONK artifacts have /// already been built. -pub fn export_solidity_groth16_verifier(output_dir: impl Into) -> Result<()> { +pub fn export_solidity_plonk_bn254_verifier(output_dir: impl Into) -> Result<()> { let output_dir: PathBuf = output_dir.into(); let artifacts_dir = if sp1_prover::build::sp1_dev_mode() { - sp1_prover::build::groth16_artifacts_dev_dir() + sp1_prover::build::plonk_bn254_artifacts_dev_dir() } else { - sp1_prover::build::try_install_groth16_artifacts() + sp1_prover::build::try_install_plonk_bn254_artifacts() }; let verifier_path = artifacts_dir.join("SP1Verifier.sol"); @@ -79,7 +81,7 @@ pub async fn download_file( mod tests { #[test] fn test_verifier_export() { - crate::artifacts::export_solidity_groth16_verifier(tempfile::tempdir().unwrap().path()) + crate::artifacts::export_solidity_plonk_bn254_verifier(tempfile::tempdir().unwrap().path()) .expect("failed to export verifier"); } } diff --git a/sdk/src/lib.rs b/sdk/src/lib.rs index 1249fc0c88..ba90d84596 100644 --- a/sdk/src/lib.rs +++ b/sdk/src/lib.rs @@ -26,7 +26,7 @@ pub use provers::{LocalProver, MockProver, NetworkProver, Prover}; use serde::{de::DeserializeOwned, Deserialize, Serialize}; use sp1_core::stark::{MachineVerificationError, ShardProof}; pub use sp1_prover::{ - CoreSC, Groth16Proof, HashableKey, InnerSC, OuterSC, PlonkBn254Proof, SP1Prover, SP1ProvingKey, + CoreSC, HashableKey, InnerSC, OuterSC, PlonkBn254Proof, SP1Prover, SP1ProvingKey, SP1PublicValues, SP1Stdin, SP1VerifyingKey, }; @@ -54,11 +54,8 @@ pub type SP1ProofVerificationError = MachineVerificationError; pub type SP1CompressedProof = SP1ProofWithPublicValues>; pub type SP1CompressedProofVerificationError = MachineVerificationError; -/// A [SP1ProofWithPublicValues] generated with [ProverClient::prove_groth16]. -pub type SP1Groth16Proof = SP1ProofWithPublicValues; - -/// A [SP1ProofWithPublicValues] generated with [ProverClient::prove_plonk]. -pub type SP1PlonkProof = SP1ProofWithPublicValues; +/// A [SP1ProofWithPublicValues] generated with [ProverClient::prove_plonk_bn254]. +pub type SP1PlonkBn254Proof = SP1ProofWithPublicValues; impl ProverClient { /// Creates a new [ProverClient]. @@ -200,7 +197,7 @@ impl ProverClient { /// /// Returns a proof of the program's execution. By default the proof generated will not be /// compressed to constant size. To create a more succinct proof, use the [Self::prove_compressed], - /// [Self::prove_groth16], or [Self::prove_plonk] methods. + /// [Self::prove_plonk_bn254], or [Self::prove_plonk] methods. /// /// ### Examples /// ```no_run @@ -259,39 +256,9 @@ impl ProverClient { self.prover.prove_compressed(pk, stdin) } - /// Proves the execution of the given program with the given input in the groth16 mode. - /// - /// Returns a proof of the program's execution in the groth16 format. The proof is a succinct - /// proof that is of constant size and friendly for on-chain verification. - /// - /// ### Examples - /// ```no_run - /// use sp1_sdk::{ProverClient, SP1Stdin}; - /// - /// // Load the program. - /// let elf = include_bytes!("../../examples/fibonacci/program/elf/riscv32im-succinct-zkvm-elf"); - /// - /// // Initialize the prover client. - /// let client = ProverClient::new(); - /// - /// // Setup the program. - /// let (pk, vk) = client.setup(elf); - /// - /// // Setup the inputs. - /// let mut stdin = SP1Stdin::new(); - /// stdin.write(&10usize); - /// - /// // Generate the proof. - /// let proof = client.prove_groth16(&pk, stdin).unwrap(); - /// ``` - /// Generates a groth16 proof, verifiable onchain, of the given elf and stdin. - pub fn prove_groth16(&self, pk: &SP1ProvingKey, stdin: SP1Stdin) -> Result { - self.prover.prove_groth16(pk, stdin) - } - - /// Proves the execution of the given program with the given input in the plonk mode. + /// Proves the execution of the given program with the given input in the plonk bn254 mode. /// - /// Returns a proof of the program's execution in the plonk format. The proof is a succinct + /// Returns a proof of the program's execution in the plonk bn254format. The proof is a succinct /// proof that is of constant size and friendly for on-chain verification. /// /// ### Examples @@ -312,10 +279,15 @@ impl ProverClient { /// stdin.write(&10usize); /// /// // Generate the proof. - /// let proof = client.prove_plonk(&pk, stdin).unwrap(); + /// let proof = client.prove_plonk_bn254(&pk, stdin).unwrap(); /// ``` - pub fn prove_plonk(&self, pk: &SP1ProvingKey, stdin: SP1Stdin) -> Result { - self.prover.prove_plonk(pk, stdin) + /// Generates a plonk bn254 proof, verifiable onchain, of the given elf and stdin. + pub fn prove_plonk_bn254( + &self, + pk: &SP1ProvingKey, + stdin: SP1Stdin, + ) -> Result { + self.prover.prove_plonk_bn254(pk, stdin) } /// Verifies that the given proof is valid and matches the given verification key produced by @@ -373,7 +345,7 @@ impl ProverClient { self.prover.verify_compressed(proof, vkey) } - /// Verifies that the given groth16 proof is valid and matches the given verification key + /// Verifies that the given plonk bn254 proof is valid and matches the given verification key /// produced by [Self::setup]. /// /// ### Examples @@ -394,43 +366,17 @@ impl ProverClient { /// stdin.write(&10usize); /// /// // Generate the proof. - /// let proof = client.prove_groth16(&pk, stdin).unwrap(); + /// let proof = client.prove_plonk_bn254(&pk, stdin).unwrap(); /// /// // Verify the proof. - /// client.verify_groth16(&proof, &vk).unwrap(); + /// client.verify_plonk_bn254(&proof, &vk).unwrap(); /// ``` - pub fn verify_groth16(&self, proof: &SP1Groth16Proof, vkey: &SP1VerifyingKey) -> Result<()> { - self.prover.verify_groth16(proof, vkey) - } - - /// Verifies that the given plonk proof is valid and matches the given verification key - /// produced by [Self::setup]. - /// - /// ### Examples - /// ```no_run - /// use sp1_sdk::{ProverClient, SP1Stdin}; - /// - /// // Load the program. - /// let elf = include_bytes!("../../examples/fibonacci/program/elf/riscv32im-succinct-zkvm-elf"); - /// - /// // Initialize the prover client. - /// let client = ProverClient::new(); - /// - /// // Setup the program. - /// let (pk, vk) = client.setup(elf); - /// - /// // Setup the inputs. - /// let mut stdin = SP1Stdin::new(); - /// stdin.write(&10usize); - /// - /// // Generate the proof. - /// let proof = client.prove_plonk(&pk, stdin).unwrap(); - /// - /// // Verify the proof. - /// client.verify_plonk(&proof, &vk).unwrap(); - /// ``` - pub fn verify_plonk(&self, proof: &SP1PlonkProof, vkey: &SP1VerifyingKey) -> Result<()> { - self.prover.verify_plonk(proof, vkey) + pub fn verify_plonk_bn254( + &self, + proof: &SP1PlonkBn254Proof, + vkey: &SP1VerifyingKey, + ) -> Result<()> { + self.prover.verify_plonk_bn254(proof, vkey) } } @@ -454,7 +400,7 @@ impl SP1ProofWithPublicValues

String { format!("0x{}", self.proof.encoded_proof.clone()) } @@ -501,7 +447,7 @@ mod tests { } #[test] - fn test_e2e_prove_groth16() { + fn test_e2e_prove_plonk_bn254() { utils::setup_logger(); let client = ProverClient::local(); let elf = @@ -509,8 +455,8 @@ mod tests { let (pk, vk) = client.setup(elf); let mut stdin = SP1Stdin::new(); stdin.write(&10usize); - let proof = client.prove_groth16(&pk, stdin).unwrap(); - client.verify_groth16(&proof, &vk).unwrap(); + let proof = client.prove_plonk_bn254(&pk, stdin).unwrap(); + client.verify_plonk_bn254(&proof, &vk).unwrap(); } #[test] @@ -527,7 +473,7 @@ mod tests { } #[test] - fn test_e2e_prove_groth16_mock() { + fn test_e2e_prove_plonk_bn254_mock() { utils::setup_logger(); let client = ProverClient::mock(); let elf = @@ -535,7 +481,7 @@ mod tests { let (pk, vk) = client.setup(elf); let mut stdin = SP1Stdin::new(); stdin.write(&10usize); - let proof = client.prove_groth16(&pk, stdin).unwrap(); - client.verify_groth16(&proof, &vk).unwrap(); + let proof = client.prove_plonk_bn254(&pk, stdin).unwrap(); + client.verify_plonk_bn254(&proof, &vk).unwrap(); } } diff --git a/sdk/src/proto/network.rs b/sdk/src/proto/network.rs index 9c0492a738..3c8919d7e6 100644 --- a/sdk/src/proto/network.rs +++ b/sdk/src/proto/network.rs @@ -300,8 +300,6 @@ pub enum ProofMode { Compressed = 2, /// The proof mode for a PlonK proof. Plonk = 3, - /// The proof mode for a Groth16 proof. - Groth16 = 4, } impl ProofMode { /// String value of the enum field names used in the ProtoBuf definition. @@ -314,7 +312,6 @@ impl ProofMode { ProofMode::Core => "PROOF_MODE_CORE", ProofMode::Compressed => "PROOF_MODE_COMPRESSED", ProofMode::Plonk => "PROOF_MODE_PLONK", - ProofMode::Groth16 => "PROOF_MODE_GROTH16", } } /// Creates an enum from field names used in the ProtoBuf definition. @@ -324,7 +321,6 @@ impl ProofMode { "PROOF_MODE_CORE" => Some(Self::Core), "PROOF_MODE_COMPRESSED" => Some(Self::Compressed), "PROOF_MODE_PLONK" => Some(Self::Plonk), - "PROOF_MODE_GROTH16" => Some(Self::Groth16), _ => None, } } diff --git a/sdk/src/provers/local.rs b/sdk/src/provers/local.rs index 35a1a42519..82664c2aad 100644 --- a/sdk/src/provers/local.rs +++ b/sdk/src/provers/local.rs @@ -3,7 +3,7 @@ use cfg_if::cfg_if; use sp1_prover::{SP1Prover, SP1Stdin}; use crate::{ - Prover, SP1CompressedProof, SP1Groth16Proof, SP1PlonkProof, SP1Proof, SP1ProofWithPublicValues, + Prover, SP1CompressedProof, SP1PlonkBn254Proof, SP1Proof, SP1ProofWithPublicValues, SP1ProvingKey, SP1VerifyingKey, }; @@ -54,9 +54,9 @@ impl Prover for LocalProver { }) } - fn prove_groth16(&self, pk: &SP1ProvingKey, stdin: SP1Stdin) -> Result { + fn prove_plonk_bn254(&self, pk: &SP1ProvingKey, stdin: SP1Stdin) -> Result { cfg_if! { - if #[cfg(feature = "groth16")] { + if #[cfg(feature = "plonk_bn254")] { let proof = self.prover.prove_core(pk, &stdin)?; let deferred_proofs = stdin.proofs.iter().map(|p| p.0.clone()).collect(); @@ -65,41 +65,25 @@ impl Prover for LocalProver { let compress_proof = self.prover.shrink(reduce_proof)?; let outer_proof = self.prover.wrap_bn254(compress_proof)?; - let groth16_aritfacts = if sp1_prover::build::sp1_dev_mode() { - sp1_prover::build::try_build_groth16_artifacts_dev( + let plonk_bn254_aritfacts = if sp1_prover::build::sp1_dev_mode() { + sp1_prover::build::try_build_plonk_bn254_artifacts_dev( &self.prover.wrap_vk, &outer_proof.proof, ) } else { - sp1_prover::build::try_install_groth16_artifacts() + sp1_prover::build::try_install_plonk_bn254_artifacts() }; - let proof = self.prover.wrap_groth16(outer_proof, &groth16_aritfacts); + let proof = self.prover.wrap_plonk_bn254(outer_proof, &plonk_bn254_aritfacts); Ok(SP1ProofWithPublicValues { proof, stdin, public_values, }) } else { - panic!("groth16 feature not enabled") + panic!("plonk bn254 feature not enabled") } } } - - fn prove_plonk(&self, _pk: &SP1ProvingKey, _stdin: SP1Stdin) -> Result { - // 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(&pk.vk, reduce_proof); - // let outer_proof = self.prover.wrap_bn254(&pk.vk, compress_proof); - // let proof = self.prover.wrap_plonk(outer_proof, artifacts_dir); - // Ok(SP1ProofWithPublicValues { - // proof, - // stdin, - // public_values, - // }) - todo!() - } } impl Default for LocalProver { diff --git a/sdk/src/provers/mock.rs b/sdk/src/provers/mock.rs index 390c494240..239127c99e 100644 --- a/sdk/src/provers/mock.rs +++ b/sdk/src/provers/mock.rs @@ -1,12 +1,12 @@ #![allow(unused_variables)] use crate::{ - Prover, SP1CompressedProof, SP1Groth16Proof, SP1PlonkProof, SP1Proof, - SP1ProofVerificationError, SP1ProofWithPublicValues, SP1ProvingKey, SP1VerifyingKey, + Prover, SP1CompressedProof, SP1PlonkBn254Proof, SP1Proof, SP1ProofVerificationError, + SP1ProofWithPublicValues, SP1ProvingKey, SP1VerifyingKey, }; use anyhow::Result; use p3_field::PrimeField; use sp1_prover::{ - verify::verify_groth16_public_inputs, Groth16Proof, HashableKey, SP1Prover, SP1Stdin, + verify::verify_plonk_bn254_public_inputs, HashableKey, PlonkBn254Proof, SP1Prover, SP1Stdin, }; /// An implementation of [crate::ProverClient] that can generate mock proofs. @@ -52,10 +52,10 @@ impl Prover for MockProver { unimplemented!() } - fn prove_groth16(&self, pk: &SP1ProvingKey, stdin: SP1Stdin) -> Result { + fn prove_plonk_bn254(&self, pk: &SP1ProvingKey, stdin: SP1Stdin) -> Result { let public_values = SP1Prover::execute(&pk.elf, &stdin)?; - Ok(SP1Groth16Proof { - proof: Groth16Proof { + Ok(SP1PlonkBn254Proof { + proof: PlonkBn254Proof { public_inputs: [ pk.vk.hash_bn254().as_canonical_biguint().to_string(), public_values.hash().to_string(), @@ -68,10 +68,6 @@ impl Prover for MockProver { }) } - fn prove_plonk(&self, pk: &SP1ProvingKey, stdin: SP1Stdin) -> Result { - todo!() - } - fn verify( &self, _proof: &SP1Proof, @@ -88,12 +84,8 @@ impl Prover for MockProver { Ok(()) } - fn verify_groth16(&self, proof: &SP1Groth16Proof, vkey: &SP1VerifyingKey) -> Result<()> { - verify_groth16_public_inputs(vkey, &proof.public_values, &proof.proof.public_inputs)?; - Ok(()) - } - - fn verify_plonk(&self, _proof: &SP1PlonkProof, _vkey: &SP1VerifyingKey) -> Result<()> { + fn verify_plonk_bn254(&self, proof: &SP1PlonkBn254Proof, vkey: &SP1VerifyingKey) -> Result<()> { + verify_plonk_bn254_public_inputs(vkey, &proof.public_values, &proof.proof.public_inputs)?; Ok(()) } } diff --git a/sdk/src/provers/mod.rs b/sdk/src/provers/mod.rs index 8475a0f7aa..fb11e5a7bf 100644 --- a/sdk/src/provers/mod.rs +++ b/sdk/src/provers/mod.rs @@ -2,7 +2,7 @@ mod local; mod mock; mod network; -use crate::{SP1CompressedProof, SP1Groth16Proof, SP1PlonkProof, SP1Proof}; +use crate::{SP1CompressedProof, SP1PlonkBn254Proof, SP1Proof}; use anyhow::Result; pub use local::LocalProver; pub use mock::MockProver; @@ -28,11 +28,8 @@ pub trait Prover: Send + Sync { /// Generate a compressed proof of the execution of a RISCV ELF with the given inputs. fn prove_compressed(&self, pk: &SP1ProvingKey, stdin: SP1Stdin) -> Result; - /// Given an SP1 program and input, generate a Groth16 proof that can be verified on-chain. - fn prove_groth16(&self, pk: &SP1ProvingKey, stdin: SP1Stdin) -> Result; - /// Given an SP1 program and input, generate a PLONK proof that can be verified on-chain. - fn prove_plonk(&self, pk: &SP1ProvingKey, stdin: SP1Stdin) -> Result; + fn prove_plonk_bn254(&self, pk: &SP1ProvingKey, stdin: SP1Stdin) -> Result; /// Verify that an SP1 proof is valid given its vkey and metadata. fn verify( @@ -56,23 +53,23 @@ pub trait Prover: Send + Sync { .map_err(|e| e.into()) } - /// Verify that a SP1 Groth16 proof is valid. Verify that the public inputs of the Groth16Proof match + /// Verify that a SP1 PLONK proof is valid. Verify that the public inputs of the PlonkBn254 proof match /// the hash of the VK and the committed public values of the SP1ProofWithPublicValues. - fn verify_groth16(&self, proof: &SP1Groth16Proof, vkey: &SP1VerifyingKey) -> Result<()> { + fn verify_plonk_bn254(&self, proof: &SP1PlonkBn254Proof, vkey: &SP1VerifyingKey) -> Result<()> { let sp1_prover = self.sp1_prover(); - let groth16_aritfacts = if sp1_prover::build::sp1_dev_mode() { - sp1_prover::build::groth16_artifacts_dev_dir() + let plonk_bn254_aritfacts = if sp1_prover::build::sp1_dev_mode() { + sp1_prover::build::plonk_bn254_artifacts_dev_dir() } else { - sp1_prover::build::groth16_artifacts_dir() + sp1_prover::build::plonk_bn254_artifacts_dir() }; - sp1_prover.verify_groth16(&proof.proof, vkey, &proof.public_values, &groth16_aritfacts)?; - - Ok(()) - } + sp1_prover.verify_plonk_bn254( + &proof.proof, + vkey, + &proof.public_values, + &plonk_bn254_aritfacts, + )?; - /// Verify that a SP1 PLONK proof is valid given its vkey and metadata. - fn verify_plonk(&self, _proof: &SP1PlonkProof, _vkey: &SP1VerifyingKey) -> Result<()> { Ok(()) } } diff --git a/sdk/src/provers/network.rs b/sdk/src/provers/network.rs index 4e9dc0f9c0..2e737ea95d 100644 --- a/sdk/src/provers/network.rs +++ b/sdk/src/provers/network.rs @@ -6,9 +6,7 @@ use crate::{ proto::network::{ProofStatus, TransactionStatus}, Prover, }; -use crate::{ - SP1CompressedProof, SP1Groth16Proof, SP1PlonkProof, SP1Proof, SP1ProvingKey, SP1VerifyingKey, -}; +use crate::{SP1CompressedProof, SP1PlonkBn254Proof, SP1Proof, SP1ProvingKey, SP1VerifyingKey}; use anyhow::{Context, Result}; use serde::de::DeserializeOwned; use sp1_core::runtime::{Program, Runtime}; @@ -171,11 +169,7 @@ impl Prover for NetworkProver { block_on(self.prove_async(&pk.elf, stdin, ProofMode::Compressed)) } - fn prove_groth16(&self, pk: &SP1ProvingKey, stdin: SP1Stdin) -> Result { - block_on(self.prove_async(&pk.elf, stdin, ProofMode::Groth16)) - } - - fn prove_plonk(&self, pk: &SP1ProvingKey, stdin: SP1Stdin) -> Result { + fn prove_plonk_bn254(&self, pk: &SP1ProvingKey, stdin: SP1Stdin) -> Result { block_on(self.prove_async(&pk.elf, stdin, ProofMode::Plonk)) } }