Skip to content

Commit

Permalink
refactor: prove_plonk (#827)
Browse files Browse the repository at this point in the history
  • Loading branch information
ratankaliani authored May 29, 2024
1 parent 6473e76 commit b8e378b
Show file tree
Hide file tree
Showing 17 changed files with 50 additions and 58 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ jobs:
with:
command: test
toolchain: nightly-2024-04-17
args: --release -p sp1-sdk --features plonk_bn254 -- test_e2e_prove_plonk_bn254 --nocapture
args: --release -p sp1-sdk --features plonk -- test_e2e_prove_plonk --nocapture
env:
RUSTFLAGS: -Copt-level=3 -Cdebug-assertions -Coverflow-checks=y -Cdebuginfo=0 -C target-cpu=native
RUST_BACKTRACE: 1
4 changes: 2 additions & 2 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:
with:
command: test
toolchain: nightly-2024-04-17
args: --release --features plonk_bn254
args: --release --features plonk
env:
RUSTFLAGS: -Copt-level=3 -Cdebug-assertions -Coverflow-checks=y -Cdebuginfo=0 -C target-cpu=native
RUST_BACKTRACE: 1
Expand Down Expand Up @@ -76,7 +76,7 @@ jobs:
with:
command: test
toolchain: nightly-2024-04-17
args: --release --features plonk_bn254
args: --release --features plonk
env:
RUSTFLAGS: -Copt-level=3 -Cdebug-assertions -Coverflow-checks=y -Cdebuginfo=0 -C target-cpu=native
RUST_BACKTRACE: 1
Expand Down
8 changes: 4 additions & 4 deletions book/verifying-proofs/solidity-and-evm.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ of using SP1 for on-chain usecases, refer to the [SP1 Project Template](https://

## 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_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.
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`. 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 PLONK Bn254 proofs require a trusted setup, the PLONK Bn254 prover is only guaranteed to work on official releases of SP1.**
**The PLONK Bn254 prover is only guaranteed to work on official releases of SP1.**

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.
To use PLONK proving & verification locally, enable the `plonk` feature flag in the sp1-sdk and ensure that Go >1.22.1 is installed.
```toml
sp1-sdk = { features = ["plonk_bn254"] }
sp1-sdk = { features = ["plonk"] }
```


Expand Down
2 changes: 1 addition & 1 deletion examples/aggregation/script/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ default-run = "sp1-aggregation-example-script"

[dependencies]
hex = "0.4.3"
sp1-sdk = { path = "../../../sdk", features = ["plonk_bn254"] }
sp1-sdk = { path = "../../../sdk", features = ["plonk"] }
tracing = "0.1.40"

[build-dependencies]
Expand Down
2 changes: 1 addition & 1 deletion examples/aggregation/script/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ fn main() {

// Generate the plonk bn254 proof.
client
.prove_plonk_bn254(&aggregation_pk, stdin)
.prove_plonk(&aggregation_pk, stdin)
.expect("proving failed");
});
}
4 changes: 2 additions & 2 deletions examples/fibonacci/script/bin/plonk_bn254.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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_plonk_bn254(&pk, stdin).unwrap();
let mut proof = client.prove_plonk(&pk, stdin).unwrap();

println!("generated proof");

Expand All @@ -29,7 +29,7 @@ fn main() {

// Verify proof and public values
client
.verify_plonk_bn254(&proof, &vk)
.verify_plonk(&proof, &vk)
.expect("verification failed");

// Save the proof.
Expand Down
4 changes: 2 additions & 2 deletions prover/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ name = "e2e"
path = "scripts/e2e.rs"

[features]
default = ["plonk_bn254"]
default = ["plonk"]

neon = ["sp1-core/neon"]
plonk_bn254 = ["sp1-recursion-gnark-ffi/plonk_bn254"]
plonk = ["sp1-recursion-gnark-ffi/plonk"]
4 changes: 2 additions & 2 deletions recursion/gnark-ffi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@ cc = "1.0"
cfg-if = "1.0"

[features]
default = ["plonk_bn254"]
default = ["plonk"]

plonk_bn254 = []
plonk = []
2 changes: 1 addition & 1 deletion recursion/gnark-ffi/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 = "plonk_bn254")] {
if #[cfg(feature = "plonk")] {
println!("cargo:rerun-if-changed=go");
// Define the output directory
let out_dir = env::var("OUT_DIR").unwrap();
Expand Down
20 changes: 10 additions & 10 deletions recursion/gnark-ffi/src/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ use std::ffi::{c_char, CString};

#[allow(warnings, clippy::all)]
mod bind {
#[cfg(feature = "plonk_bn254")]
#[cfg(feature = "plonk")]
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
}
use bind::*;

pub fn prove_plonk_bn254(data_dir: &str, witness_path: &str) -> PlonkBn254Proof {
cfg_if! {
if #[cfg(feature = "plonk_bn254")] {
if #[cfg(feature = "plonk")] {
let data_dir = CString::new(data_dir).expect("CString::new failed");
let witness_path = CString::new(witness_path).expect("CString::new failed");

Expand All @@ -31,21 +31,21 @@ pub fn prove_plonk_bn254(data_dir: &str, witness_path: &str) -> PlonkBn254Proof

proof.into_rust()
} else {
panic!("plonk_bn254 feature not enabled");
panic!("plonk feature not enabled");
}
}
}

pub fn build_plonk_bn254(data_dir: &str) {
cfg_if! {
if #[cfg(feature = "plonk_bn254")] {
if #[cfg(feature = "plonk")] {
let data_dir = CString::new(data_dir).expect("CString::new failed");

unsafe {
bind::BuildPlonkBn254(data_dir.as_ptr() as *mut c_char);
}
} else {
panic!("plonk_bn254 feature not enabled");
panic!("plonk feature not enabled");

}
}
Expand All @@ -58,7 +58,7 @@ pub fn verify_plonk_bn254(
committed_values_digest: &str,
) -> Result<(), String> {
cfg_if! {
if #[cfg(feature = "plonk_bn254")] {
if #[cfg(feature = "plonk")] {
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");
Expand All @@ -81,14 +81,14 @@ pub fn verify_plonk_bn254(
Err(err.into_string().unwrap())
}
} else {
panic!("plonk_bn254 feature not enabled");
panic!("plonk feature not enabled");
}
}
}

pub fn test_plonk_bn254(witness_json: &str, constraints_json: &str) {
cfg_if! {
if #[cfg(feature = "plonk_bn254")] {
if #[cfg(feature = "plonk")] {
unsafe {
let witness_json = CString::new(witness_json).expect("CString::new failed");
let build_dir = CString::new(constraints_json).expect("CString::new failed");
Expand All @@ -103,7 +103,7 @@ pub fn test_plonk_bn254(witness_json: &str, constraints_json: &str) {
}
}
} else {
panic!("plonk_bn254 feature not enabled");
panic!("plonk feature not enabled");
}
}
}
Expand All @@ -121,7 +121,7 @@ unsafe fn c_char_ptr_to_string(input: *mut c_char) -> String {
}
}

#[cfg(feature = "plonk_bn254")]
#[cfg(feature = "plonk")]
impl C_PlonkBn254Proof {
/// Converts a C PlonkBn254Proof into a Rust PlonkBn254Proof, freeing the C strings.
fn into_rust(self) -> PlonkBn254Proof {
Expand Down
2 changes: 1 addition & 1 deletion sdk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ ethers = { version = "2", default-features = false }

[features]
neon = ["sp1-core/neon"]
plonk_bn254 = ["sp1-prover/plonk_bn254"]
plonk = ["sp1-prover/plonk"]

[build-dependencies]
vergen = { version = "8", default-features = false, features = [
Expand Down
2 changes: 1 addition & 1 deletion sdk/src/artifacts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ pub use sp1_prover::build::{
build_plonk_bn254_artifacts_with_dummy, try_install_plonk_bn254_artifacts,
};

/// Exports the soliditiy verifier for PLONK proofs to the specified output directory.
/// Exports the solidity verifier for PLONK proofs to the specified output directory.
///
/// WARNING: If you are on development mode, this function assumes that the PLONK artifacts have
/// already been built.
Expand Down
38 changes: 15 additions & 23 deletions sdk/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ pub type SP1ProofVerificationError = MachineVerificationError<CoreSC>;
pub type SP1CompressedProof = SP1ProofWithPublicValues<ShardProof<InnerSC>>;
pub type SP1CompressedProofVerificationError = MachineVerificationError<InnerSC>;

/// A [SP1ProofWithPublicValues] generated with [ProverClient::prove_plonk_bn254].
/// A [SP1ProofWithPublicValues] generated with [ProverClient::prove_plonk].
pub type SP1PlonkBn254Proof = SP1ProofWithPublicValues<PlonkBn254Proof>;

impl ProverClient {
Expand Down Expand Up @@ -197,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_plonk_bn254], or [Self::prove_plonk] methods.
/// [Self::prove_plonk], or [Self::prove_plonk] methods.
///
/// ### Examples
/// ```no_run
Expand Down Expand Up @@ -279,15 +279,11 @@ impl ProverClient {
/// stdin.write(&10usize);
///
/// // Generate the proof.
/// let proof = client.prove_plonk_bn254(&pk, stdin).unwrap();
/// let proof = client.prove_plonk(&pk, stdin).unwrap();
/// ```
/// Generates a plonk bn254 proof, verifiable onchain, of the given elf and stdin.
pub fn prove_plonk_bn254(
&self,
pk: &SP1ProvingKey,
stdin: SP1Stdin,
) -> Result<SP1PlonkBn254Proof> {
self.prover.prove_plonk_bn254(pk, stdin)
pub fn prove_plonk(&self, pk: &SP1ProvingKey, stdin: SP1Stdin) -> Result<SP1PlonkBn254Proof> {
self.prover.prove_plonk(pk, stdin)
}

/// Verifies that the given proof is valid and matches the given verification key produced by
Expand Down Expand Up @@ -366,17 +362,13 @@ impl ProverClient {
/// stdin.write(&10usize);
///
/// // Generate the proof.
/// let proof = client.prove_plonk_bn254(&pk, stdin).unwrap();
/// let proof = client.prove_plonk(&pk, stdin).unwrap();
///
/// // Verify the proof.
/// client.verify_plonk_bn254(&proof, &vk).unwrap();
/// client.verify_plonk(&proof, &vk).unwrap();
/// ```
pub fn verify_plonk_bn254(
&self,
proof: &SP1PlonkBn254Proof,
vkey: &SP1VerifyingKey,
) -> Result<()> {
self.prover.verify_plonk_bn254(proof, vkey)
pub fn verify_plonk(&self, proof: &SP1PlonkBn254Proof, vkey: &SP1VerifyingKey) -> Result<()> {
self.prover.verify_plonk(proof, vkey)
}
}

Expand Down Expand Up @@ -447,16 +439,16 @@ mod tests {
}

#[test]
fn test_e2e_prove_plonk_bn254() {
fn test_e2e_prove_plonk() {
utils::setup_logger();
let client = ProverClient::local();
let elf =
include_bytes!("../../examples/fibonacci/program/elf/riscv32im-succinct-zkvm-elf");
let (pk, vk) = client.setup(elf);
let mut stdin = SP1Stdin::new();
stdin.write(&10usize);
let proof = client.prove_plonk_bn254(&pk, stdin).unwrap();
client.verify_plonk_bn254(&proof, &vk).unwrap();
let proof = client.prove_plonk(&pk, stdin).unwrap();
client.verify_plonk(&proof, &vk).unwrap();
}

#[test]
Expand All @@ -473,15 +465,15 @@ mod tests {
}

#[test]
fn test_e2e_prove_plonk_bn254_mock() {
fn test_e2e_prove_plonk_mock() {
utils::setup_logger();
let client = ProverClient::mock();
let elf =
include_bytes!("../../examples/fibonacci/program/elf/riscv32im-succinct-zkvm-elf");
let (pk, vk) = client.setup(elf);
let mut stdin = SP1Stdin::new();
stdin.write(&10usize);
let proof = client.prove_plonk_bn254(&pk, stdin).unwrap();
client.verify_plonk_bn254(&proof, &vk).unwrap();
let proof = client.prove_plonk(&pk, stdin).unwrap();
client.verify_plonk(&proof, &vk).unwrap();
}
}
4 changes: 2 additions & 2 deletions sdk/src/provers/local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@ impl Prover for LocalProver {
})
}

fn prove_plonk_bn254(&self, pk: &SP1ProvingKey, stdin: SP1Stdin) -> Result<SP1PlonkBn254Proof> {
fn prove_plonk(&self, pk: &SP1ProvingKey, stdin: SP1Stdin) -> Result<SP1PlonkBn254Proof> {
cfg_if! {
if #[cfg(feature = "plonk_bn254")] {
if #[cfg(feature = "plonk")] {

let proof = self.prover.prove_core(pk, &stdin)?;
let deferred_proofs = stdin.proofs.iter().map(|p| p.0.clone()).collect();
Expand Down
4 changes: 2 additions & 2 deletions sdk/src/provers/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ impl Prover for MockProver {
unimplemented!()
}

fn prove_plonk_bn254(&self, pk: &SP1ProvingKey, stdin: SP1Stdin) -> Result<SP1PlonkBn254Proof> {
fn prove_plonk(&self, pk: &SP1ProvingKey, stdin: SP1Stdin) -> Result<SP1PlonkBn254Proof> {
let public_values = SP1Prover::execute(&pk.elf, &stdin)?;
Ok(SP1PlonkBn254Proof {
proof: PlonkBn254Proof {
Expand Down Expand Up @@ -84,7 +84,7 @@ impl Prover for MockProver {
Ok(())
}

fn verify_plonk_bn254(&self, proof: &SP1PlonkBn254Proof, vkey: &SP1VerifyingKey) -> Result<()> {
fn verify_plonk(&self, proof: &SP1PlonkBn254Proof, vkey: &SP1VerifyingKey) -> Result<()> {
verify_plonk_bn254_public_inputs(vkey, &proof.public_values, &proof.proof.public_inputs)?;
Ok(())
}
Expand Down
4 changes: 2 additions & 2 deletions sdk/src/provers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ pub trait Prover: Send + Sync {
fn prove_compressed(&self, pk: &SP1ProvingKey, stdin: SP1Stdin) -> Result<SP1CompressedProof>;

/// Given an SP1 program and input, generate a PLONK proof that can be verified on-chain.
fn prove_plonk_bn254(&self, pk: &SP1ProvingKey, stdin: SP1Stdin) -> Result<SP1PlonkBn254Proof>;
fn prove_plonk(&self, pk: &SP1ProvingKey, stdin: SP1Stdin) -> Result<SP1PlonkBn254Proof>;

/// Verify that an SP1 proof is valid given its vkey and metadata.
fn verify(
Expand All @@ -55,7 +55,7 @@ pub trait Prover: Send + Sync {

/// 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_plonk_bn254(&self, proof: &SP1PlonkBn254Proof, vkey: &SP1VerifyingKey) -> Result<()> {
fn verify_plonk(&self, proof: &SP1PlonkBn254Proof, vkey: &SP1VerifyingKey) -> Result<()> {
let sp1_prover = self.sp1_prover();

let plonk_bn254_aritfacts = if sp1_prover::build::sp1_dev_mode() {
Expand Down
2 changes: 1 addition & 1 deletion sdk/src/provers/network.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ impl Prover for NetworkProver {
block_on(self.prove_async(&pk.elf, stdin, ProofMode::Compressed))
}

fn prove_plonk_bn254(&self, pk: &SP1ProvingKey, stdin: SP1Stdin) -> Result<SP1PlonkBn254Proof> {
fn prove_plonk(&self, pk: &SP1ProvingKey, stdin: SP1Stdin) -> Result<SP1PlonkBn254Proof> {
block_on(self.prove_async(&pk.elf, stdin, ProofMode::Plonk))
}
}
Expand Down

0 comments on commit b8e378b

Please sign in to comment.