This crate verifies Groth16 proofs generated with SP1, leveraging Solana's BN254 precompiles for efficient cryptographic operations.
Caution
This repository is under active development and is not yet ready for production use.
The sp1-solana
library itself is in the verifier
directory. example/program
contains an example Solana program that uses this library to verify SP1 proofs, and example/script
contains an example Solana script that invokes this program.
- Groth16 Proof Verification: Implements the Groth16 protocol for zero-knowledge proof verification.
- Solana BN254 Precompiles: Leverages Solana's native BN254 precompiles for optimized performance.
- Easy Integration: Seamlessly integrates with existing Solana programs and infrastructure.
- Extensible: Built with modularity in mind, allowing for future enhancements and integrations.
The example demonstrates how to use the sp1-solana
crate to verify a proof generated by SP1 on Solana.
Running the script will perform the following steps:
-
Load an SP1
SP1ProofWithPublicValues
from the pre-generated prooffibonacci_proof.bin
. This is a SP1 Groth16 proof that proves that the 20th fibonacci number is 6765. Optionally, this proof can be freshly generated from thesp1-program
. -
Extract the proof, public inputs, and program vkey hash from the
SP1ProofWithPublicValues
.
- The
proof
is the Groth16 proof, serialized in SP1's standard format - The
sp1_public_inputs
are the public inputs to the underlying sp1 program. - The
program_vkey_hash
is the hash of the underlying sp1 program's verification key.
Here is a snippet that demonstrates this extraction.
/// The instruction data for the program.
#[derive(BorshDeserialize, BorshSerialize)]
pub struct SP1Groth16Proof {
pub proof: Vec<u8>,
pub sp1_public_inputs: Vec<u8>,
}
...
// Load the proof from the file, and extract the proof, public inputs, and program vkey hash.
let sp1_proof_with_public_values = SP1ProofWithPublicValues::load(&proof_file).unwrap();
let groth16_proof = SP1Groth16Proof {
proof: sp1_proof_with_public_values.bytes(),
sp1_public_inputs: sp1_proof_with_public_values.public_values.to_vec(),
};
// Send the proof to the contract, and verify it on `solana-program-test`.
run_verify_instruction(groth16_proof).await;
- Using the
solana-program-test
framework, send theSP1Groth16Proof
to thefibonacci-verifier-contract
. This smart contract will verify the proof using thesp1-solana
crate against the fibonacci sp1 program vkey and print out the public inputs. Here is a snippet that demonstrates how to do some common operations on the SP1 Groth16 proof.
// Derived by running `vk.bytes32()` on the program's vkey.
const FIBONACCI_VKEY_HASH: &str =
"0083e8e370d7f0d1c463337f76c9a60b62ad7cc54c89329107c92c1e62097872";
pub fn process_instruction(
_program_id: &Pubkey,
_accounts: &[AccountInfo],
instruction_data: &[u8],
) -> ProgramResult {
// Deserialize the SP1Groth16Proof from the instruction data.
let groth16_proof = SP1Groth16Proof::try_from_slice(instruction_data)
.map_err(|_| ProgramError::InvalidInstructionData)?;
// Get the SP1 Groth16 verification key from the `sp1-solana` crate.
let vk = sp1_solana::GROTH16_VK_2_0_0_BYTES;
// Verify the proof.
verify_proof(
&groth16_proof.proof,
&groth16_proof.sp1_public_inputs,
&FIBONACCI_VKEY_HASH,
vk,
)
.map_err(|_| ProgramError::InvalidInstructionData)?;
// Print out the public values.
let mut reader = groth16_proof.sp1_public_inputs.as_slice();
let n = u32::deserialize(&mut reader).unwrap();
let a = u32::deserialize(&mut reader).unwrap();
let b = u32::deserialize(&mut reader).unwrap();
msg!("Public values: (n: {}, a: {}, b: {})", n, a, b);
Ok(())
}
To load the pregenerated proof and verify it on solana-program-test
, run the following commands.
cd script
RUST_LOG=info cargo run --release
To generate a fresh proof from the program in sp1-program
, run the following commands.
cd script
RUST_LOG=info cargo run --release -- --prove
Run the following commands to build and deploy the example solana program to devnet. These commands assume you've already created a Solana keypair locally, and you have the edge solana CLI tools 1. Request devnet sol as necessary.
cd example/program
cargo build-sbf --sbf-out-dir ./target
solana config set -ud
solana program deploy --program-id target/fibonacci_verifier_contract-keypair.json target/fibonacci_verifier_contract.so
Add sp1-solana
to your Cargo.toml
:
[dependencies]
sp1-solana = { git = "https://github.com/succinctlabs/groth16-solana" }
This crate uses the groth16-solana
crate from Light Protocol Labs for the Groth16 proof verification, and the ark-bn254
crate for the elliptic curve operations.
sh -c "$(curl -sSfL https://release.anza.xyz/edge/install)"
Footnotes
-
Run this command to install the edge solana CLI. ↩