MoPro Integration Guide

What is MoPro?

MoPro (Mobile Proving) is a framework that brings zero-knowledge proof capabilities to mobile platforms. It provides cross-platform support for iOS, Android, and Web with multiple ZK backends including Circom, and Noir.

In Deimos, MoPro is used to run benchmarks on actual mobile devices, measuring real-world performance of ZK proof generation and verification.

Architecture

┌─────────────────┐    ┌──────────────────┐    ┌─────────────────┐
│   Kotlin/Swift  │───▶│   Rust FFI       │───▶│  ZK Circuits    │
│   (Mobile App)  │    │   (UniFFI)       │    │  (Circom/Noir)  │
└─────────────────┘    └──────────────────┘    └─────────────────┘

The architecture consists of three layers:

  • Mobile App Layer: Kotlin (Android) or Swift (iOS) UI and benchmarking logic
  • FFI Layer: Rust code with UniFFI bindings for type-safe cross-language communication
  • Circuit Layer: Compiled ZK circuits (Circom or Noir)

Directory Structure

Each MoPro implementation follows a consistent pattern:

moPro/
├── mopro-sha256/                 # SHA-256 implementation
│   ├── src/
│   │   └── lib.rs               # Rust library with ZK proof functions
│   ├── android/                 # Android application
│   │   └── app/src/main/java/   # Kotlin integration code
│   ├── ios/                     # iOS application (if created)
│   ├── MoproAndroidBindings/    # Generated FFI bindings
│   ├── test-vectors/            # Test data for circuits
│   ├── Cargo.toml              # Rust dependencies
│   └── README.md               # Setup instructions
│
├── mopro-keccack256/            # Keccak-256 implementation
│   └── (same structure)
│
└── mopro-example-app/           # Example implementation
    └── (same structure)

Key directories in each MoPro implementation:

  • src/: Rust library with ZK proof functions
  • android/: Android application with Kotlin integration
  • MoproAndroidBindings/: Generated FFI bindings
  • test-vectors/: Test data for circuits
  • Cargo.toml: Rust dependencies

Setting Up MoPro

Prerequisites

  • Rust toolchain installed
  • MoPro CLI tool installed
  • Android Studio (for Android) or Xcode (for iOS)
  • Compiled circuit files (r1cs, wasm, zkey)

Install MoPro CLI

Bash
git clone https://github.com/zkmopro/mopro
cd mopro/cli
cargo install --path .

Initialize Project

Bash
cd benchmarking-suite/moPro/mopro-sha256

# Initialize MoPro configuration
mopro init

# This creates mopro-config.toml with project settings

Build Native Bindings

Bash
# Build bindings for all configured platforms
mopro build

# This compiles Rust code and generates FFI bindings

Create Platform Templates

Bash
# Generate platform-specific templates
mopro create

# This creates android/, ios/, or web/ directories with starter code

Update Bindings

Bash
# After making changes to Rust code
mopro update

# This refreshes bindings in all platform directories

Rust Implementation

Basic Structure (src/lib.rs)

use mopro_ffi::app;

// Define your app with MoPro macro
app!();

// The macro automatically generates these functions:
// - generate_circom_proof()
// - verify_circom_proof()
// - generate_halo2_proof()
// - verify_halo2_proof()
// - generate_noir_proof()
// - verify_noir_proof()

Custom Functions

You can add custom functions using the #[uniffi::export] attribute:

#[uniffi::export]
fn mopro_hello_world() -> String {
    "Hello, World!".to_string()
}

#[uniffi::export]
fn custom_benchmark_function(input: String) -> Result<String, String> {
    // Your custom logic here
    Ok("Result".to_string())
}

Cargo Configuration

[package]
name = "mopro-sha256"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["lib", "cdylib", "staticlib"]

[dependencies]
mopro-ffi = { version = "0.1", features = ["circom"] }
uniffi = "0.29.0"

[features]
default = ["mopro-ffi/circom"]
# Optional: "mopro-ffi/halo2", "mopro-ffi/noir"

Android Integration

Opening the Project

Bash
# Open in Android Studio
open android -a Android\ Studio

# Or build from command line
cd android
./gradlew build

Kotlin Usage Example

import uniffi.mopro.generateCircomProof
import uniffi.mopro.verifyCircomProof
import uniffi.mopro.ProofLib

// Prepare input JSON
val input = """
{
    "in": [72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100]
}
""".trimIndent()

// Generate proof
val proofResult = generateCircomProof(
    zkeyPath = "/path/to/circuit.zkey",
    circuitInputs = input,
    proofLib = ProofLib.ARKWORKS
)

// Verify proof
val isValid = verifyCircomProof(
    zkeyPath = "/path/to/circuit.zkey",
    proof = proofResult,
    proofLib = ProofLib.ARKWORKS
)

println("Proof valid: $isValid")

Benchmarking Implementation

// Measure proving time
val startTime = System.currentTimeMillis()
val proof = generateCircomProof(zkeyPath, input, ProofLib.ARKWORKS)
val provingTime = System.currentTimeMillis() - startTime

// Measure memory usage
val runtime = Runtime.getRuntime()
val memoryBefore = runtime.totalMemory() - runtime.freeMemory()
// ... generate proof ...
val memoryAfter = runtime.totalMemory() - runtime.freeMemory()
val memoryUsed = memoryAfter - memoryBefore

// Store results
val benchmarkResult = BenchmarkResult(
    provingTime = provingTime,
    verificationTime = verificationTime,
    memoryUsed = memoryUsed,
    proofSize = proof.length
)

iOS Integration

Opening the Project

Bash
# Open in Xcode
open ios/MoproApp.xcodeproj

# Or build from command line
cd ios
xcodebuild -project MoproApp.xcodeproj -scheme MoproApp build

Swift Usage Example

import mopro

// Prepare input
let input = """
{
    "in": [72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100]
}
"""

// Generate proof
let proof = try generateCircomProof(
    zkeyPath: "/path/to/circuit.zkey",
    circuitInputs: input,
    proofLib: .arkworks
)

// Verify proof
let isValid = try verifyCircomProof(
    zkeyPath: "/path/to/circuit.zkey",
    proof: proof,
    proofLib: .arkworks
)

print("Proof valid: \(isValid)")

Benchmarking Features

Metrics Collected

  • Proving Time: Duration of proof generation in milliseconds
  • Verification Time: Duration of proof verification in milliseconds
  • Memory Usage: Peak RAM consumption during operations in MB
  • Proof Size: Size of generated proof in bytes
  • Success Rate: Percentage of successful proof generations
  • Device Information: Model, OS version, CPU, RAM

Single Run Testing

Test individual proof generation with detailed metrics display. Useful for debugging and understanding performance characteristics.

Batch Processing

Run multiple proof generations automatically and collect statistics:

  • Average proving time
  • Minimum and maximum times
  • Standard deviation
  • Success rate
  • Memory usage patterns

Framework Comparison

Compare performance across different proving backends (Arkworks, Rapidsnark) side-by-side.

Real-time Monitoring

Live display of performance metrics during proof generation with progress indicators.

Circuit Integration

Adding Circuit Files

Place your compiled circuit files in the appropriate directory:

mopro-sha256/
├── circuits/
│   ├── sha256.wasm          # Witness generator
│   ├── sha256.zkey          # Proving key
│   └── verification_key.json # Verification key
└── test-vectors/
    └── input.json           # Test inputs

Configuring Circuit Paths

Update your app to reference the circuit files. On Android, place files in assets/ directory. On iOS, add files to the Xcode project bundle.

Loading Circuit Files

// Android - Load from assets
val zkeyPath = context.assets.open("sha256.zkey").use { input ->
    val file = File(context.filesDir, "sha256.zkey")
    file.outputStream().use { output ->
        input.copyTo(output)
    }
    file.absolutePath
}

// iOS - Load from bundle
guard let zkeyPath = Bundle.main.path(
    forResource: "sha256", 
    ofType: "zkey"
) else {
    fatalError("Circuit file not found")
}

Testing

Rust Tests

Bash
# Run all tests
cargo test

# Run specific test
cargo test test_circom

# Run with verbose output
cargo test -- --nocapture

# Run tests with release optimizations
cargo test --release

Android Tests

Bash
cd android

# Run unit tests
./gradlew test

# Run instrumented tests on device
./gradlew connectedAndroidTest

iOS Tests

Bash
cd ios

# Run tests
xcodebuild test -project MoproApp.xcodeproj -scheme MoproApp

Performance Optimization

Rust Optimization

  • Always build with --release flag for production
  • Enable LTO (Link Time Optimization) in Cargo.toml
  • Use appropriate optimization level (opt-level = 3)
  • Profile with cargo flamegraph to identify bottlenecks

Mobile Optimization

  • Test on physical devices, not emulators
  • Disable debug logging in production builds
  • Use background threads for proof generation
  • Implement proper memory management
  • Cache circuit files to avoid repeated loading

Circuit Optimization

  • Use ZK-friendly hash functions when possible (Poseidon, MiMC)
  • Minimize constraint count in circuits
  • Use appropriate Powers of Tau size (not too large)
  • Consider using Rapidsnark for faster proving

Common Issues

UniFFI Version Mismatch

Issue: Build fails with UniFFI errors

Solution: Ensure you're using UniFFI version 0.29.0 as specified in Cargo.toml. This version is pinned for compatibility.

Circuit File Not Found

Issue: App crashes when trying to load circuit files

Solution: Verify circuit files are properly included in assets (Android) or bundle (iOS). Check file paths are correct.

Out of Memory

Issue: App crashes during proof generation

Solution: Large circuits may exceed mobile device memory. Use smaller circuits or implement memory-efficient proving strategies. Test on devices with adequate RAM.

Slow Performance

Issue: Proof generation takes too long

Solution: This is expected for large circuits on mobile. Use release builds, test on physical devices, and consider using ZK-friendly hash functions.

Use Cases

Privacy-Preserving Authentication

  • Prove knowledge of password without revealing it
  • Zero-knowledge identity verification
  • Private credential systems

Blockchain Integration

  • Mobile wallet proof generation
  • Layer 2 scaling solutions
  • Private transaction validation

Performance Research

  • Mobile ZK proof benchmarking
  • Cross-platform performance analysis
  • Resource optimization studies

Resources

  • MoPro Documentation: https://zkmopro.org
  • MoPro GitHub: https://github.com/zkmopro/mopro
  • UniFFI Guide: https://mozilla.github.io/uniffi-rs
  • Circom Documentation: https://docs.circom.io
  • Community Telegram: @zkmopro
  • Community Twitter: @zkmopro

Example Projects

Check out the example implementations in the repository:

  • mopro-sha256: SHA-256 hash benchmarking app
  • mopro-keccack256: Keccak-256 hash benchmarking app
  • mopro-example-app: Basic example with all features