Skip to main content

Prove

The prove module is gated behind the prove Cargo feature. It re-exports ZK circuit construction, Groth16 proving, and serialization utilities from r14 circuit and the serialize module.

Enabling​

[dependencies]
r14-sdk = { version = "0.1", features = ["prove"] }

This pulls in arkworks, BLS12-381 curve operations, and the Groth16 prover. Compile times increase significantly - only enable in binaries that need to generate proofs.

Re-exports​

All items are available under r14_sdk::prove::.

ItemSource CrateDescription
setupr14 circuitGenerate proving key + verification key for the transfer circuit.
prover14 circuitGenerate a Groth16 proof given a TransferCircuit and proving key.
verify_offchainr14 circuitVerify a proof locally without submitting on-chain.
constraint_countr14 circuitReturns the number of R1CS constraints in the circuit.
TransferCircuitr14 circuitThe arkworks circuit struct for a 1-in-2-out private transfer.
PublicInputsr14 circuitThe public inputs struct: root, nullifier, two output commitments.
serialize_proof_for_sorobanserializeConvert Proof<Bls12_381> to hex strings for Soroban.
serialize_vk_for_sorobanserializeConvert VerifyingKey<Bls12_381> to hex strings for Soroban.
SerializedProofserializeHex-encoded proof struct (a, b, c).
SerializedVKserializeHex-encoded verification key struct.

Functions​

setup​

pub fn setup() -> (ProvingKey<Bls12_381>, VerifyingKey<Bls12_381>)

Runs Groth16 key generation for the TransferCircuit. This is expensive (several seconds) and should be done once, then reused.

prove​

pub fn prove(
pk: &ProvingKey<Bls12_381>,
circuit: TransferCircuit,
) -> R14Result<Proof<Bls12_381>>

Generates a Groth16 proof for the given circuit instance and proving key.

verify_offchain​

pub fn verify_offchain(
vk: &VerifyingKey<Bls12_381>,
public_inputs: &PublicInputs,
proof: &Proof<Bls12_381>,
) -> R14Result<bool>

Verifies a proof locally. Returns true if valid. Useful for testing before submitting on-chain.

constraint_count​

pub fn constraint_count() -> usize

Returns the number of R1CS constraints in the transfer circuit. Useful for benchmarking and CI checks.

Example: Setup and Prove​

use r14_sdk::prove::{setup, prove, verify_offchain, TransferCircuit, PublicInputs};
use r14_sdk::prove::{serialize_proof_for_soroban, serialize_vk_for_soroban};
use r14_sdk::{SecretKey, Note, commitment, nullifier, owner_hash, wallet};

let mut rng = wallet::crypto_rng();

// One-time setup
let (pk, vk) = setup();

// Build the circuit
let sk = SecretKey::random(&mut rng);
let owner = owner_hash(&sk);

let input_note = Note::new(1_000_000, 0, owner, Fr::rand(&mut rng));
let recipient_owner = owner_hash(&recipient_sk);

let circuit = TransferCircuit::new(
&sk,
&input_note,
&merkle_path,
recipient_owner,
500_000, // recipient value
500_000, // change value
0, // app_tag
&mut rng,
);

// Prove
let proof = prove(&pk, circuit)?;

// Verify locally
let public_inputs = PublicInputs {
root: merkle_root,
nullifier: nullifier(&sk, &input_note.nonce),
out_commitment_0: commitment(&recipient_note),
out_commitment_1: commitment(&change_note),
};
assert!(verify_offchain(&vk, &public_inputs, &proof)?);

// Serialize for on-chain submission
let ser_proof = serialize_proof_for_soroban(&proof);
let ser_vk = serialize_vk_for_soroban(&vk);