Native Module Setup

Platform-specific setup for the Mopro native ZKP module.

šŸ“¦ Automatic Setup

For most projects, npx @blockfact/setup handles everything automatically. This guide covers manual setup and troubleshooting.

Android Setup

1. Native Library

Copy the pre-built libblockfact_zkp.so to your Android project:

android/app/src/main/jniLibs/arm64-v8a/libblockfact_zkp.so

2. Circuit Assets

Copy the circuit proving key to Android assets:

android/app/src/main/assets/circuits/poseidon_check_final.zkey

3. Build Configuration

Ensure your build.gradle targets arm64:

android {
    defaultConfig {
        ndk {
            abiFilters "arm64-v8a"
        }
    }
}

iOS Setup

1. Static Library

Add libblockfact_zkp.a to your Xcode project and link it in Build Phases → Link Binary With Libraries.

2. Circuit Assets

Add poseidon_check_final.zkey to your Xcode project as a bundle resource (Build Phases → Copy Bundle Resources).

3. Pod Install

cd ios && pod install && cd ..

🚧 iOS Native ZKP

iOS native ZKP is under development. The shared JS code works cross-platform, but the Rust library needs to be cross-compiled for aarch64-apple-ios. iOS currently falls back to server-side ZKP generation.

Expo Projects

Native modules are not compatible with Expo Go. You need a dev client or prebuild:

npx expo prebuild
npx @blockfact/setup
npx expo run:android  # or run:ios

Graceful Fallback

If mopro-ffi is not installed or the native library fails to load, the SDK automatically falls back to server-side ZKP generation. You'll see a console warning:

āš ļø ZKP generation failed (non-blocking): mopro-ffi not available
   Falling back to server-side ZKP generation

Content registration still works — it just takes a few seconds longer because the proof is generated on the server.

Troubleshooting

dlopen failed: cannot locate symbol

The native library can't find the witness calculator symbols. This usually means the Mopro crate was built with the wrong witness name. The circuit poseidon_check.wasm must be registered as poseidoncheck (no underscore) in the Rust crate.

Rust panic / app crash during proof generation

  • • Wrong ProofLib: Must use ProofLib.Arkworks, not ProofLib.Rapidsnark
  • • Scalar inputs: Circuit inputs must be arrays (["123"] not "123") — the Rust witness calculator silently drops scalar values
  • • Wrong architecture: Ensure the .so is built for arm64-v8a, not x86_64

Public signals are ["0", "0"]

This means circuit inputs are being passed as scalars instead of arrays. The circom-prover Rust crate's json_to_hashmap only handles array values — scalar strings are silently dropped, producing an empty witness with zero public signals.

exec format error

The native library was built for the wrong CPU architecture (e.g., built on Apple Silicon for x86_64 Lambda). Rebuild with the correct target.

Verifying the Setup

After setup, take a test photo. Check the logs for:

āœ… ZKP proof generated on device (native)
āœ… ZKP_RESULT: {"proof":{"pi_a":[...],"pi_b":[...],"pi_c":[...]},"publicSignals":["123...","123..."]}

If you see publicSignals with non-zero values, native ZKP is working correctly.

Next Steps