← Back to Academy
Developer · SDK Integration

zk-IoT SDK Integration Guide

⏱ ~5 hours 🛠️ Hands-on Advanced

SDK Overview

The FidesInnova zk-IoT ZKP SDK is a library that enables IoT device firmware to generate zero-knowledge proofs (zk-SNARKs) on-device. It is the component that makes an ordinary IoT device a cryptographically trustworthy zk-Device.

The SDK implements:

  • Witness generation — computing all intermediate values in the firmware execution trace
  • R1CS satisfaction checking — verifying the witness satisfies the compiled circuit constraints
  • Groth16 proof construction — computing the three elliptic curve points that form the proof
  • Proof serialization — encoding the proof as a compact byte array for MQTT transmission

The SDK is fully open source under the MIT license. All source code is available at github.com/FidesInnova.

Performance reference (from IEEE paper): Proof generation ≈694ms (Groth16), verification ≈19ms, proof size ≈200 bytes on ESP32-class hardware. Plonk proof system is also supported: ≈777ms generation, ≈22ms verification.

Supported Platforms

ESP32 (C++)

Espressif ESP32 and ESP32-S3. The primary reference platform — all FidesInnova reference hardware (E-card V2, zk-MultiSensor, MiniSensor) is built on ESP32. Arduino IDE and ESP-IDF both supported.

ARM Cortex-M (C++)

STM32, nRF52, SAMD51, and compatible MCUs with at least 512KB flash and 256KB RAM. Bare metal and RTOS (FreeRTOS, Zephyr) supported.

RISC-V (C++)

ESP32-C3, ESP32-C6, and compatible RISC-V MCUs. Growing platform support as RISC-V adoption increases in IoT silicon.

Linux (Rust)

Raspberry Pi, NVIDIA Jetson, BeagleBone, and any armv7/aarch64/x86_64 Linux system. The Rust SDK also supports WebAssembly for browser-based verification.

Minimum Requirements

Flash: 512KB (proof generation tables). RAM: 128KB (witness computation buffer). For tighter MCUs, use the SDK's low-memory mode (trades speed for memory: ~2s proof time, 64KB RAM).

Not Yet Supported

Deeply constrained MCUs (Arduino Uno/Nano, 8-bit AVR). These lack sufficient flash for the proving key tables. Planned: proof offloading to a gateway node for these devices.

C++ SDK Integration (ESP32 Example)

Step-by-step integration for an ESP32 project using Arduino IDE or PlatformIO:

1

Install the SDK

# PlatformIO: add to platformio.ini
lib_deps = https://github.com/FidesInnova/zkp-sdk-cpp.git

# Arduino IDE: Library Manager → search "FidesInnova ZKP"
2

Initialize the SDK

#include "fidesinnova_zkp.h"

FidesZKP zkp;

void setup() {
  // Initialize with proving key stored in flash partition
  if (!zkp.begin(PROVING_KEY_PARTITION)) {
    Serial.println("ZKP init failed");
  }
}
3

Generate a Proof

void loop() {
  float temp = sensor.readTemperature();
  uint32_t ts = (uint32_t)time(nullptr);

  // Build witness input
  ZKPInput input = { .temperature = (int32_t)(temp * 100), .timestamp = ts };

  // Generate proof (~694ms blocking call)
  ZKPProof proof;
  if (zkp.generateProof(input, &proof)) {
    // Serialize and publish via MQTT
    uint8_t buf[256]; size_t len;
    zkp.serializeProof(proof, buf, &len);
    mqttPublishWithProof(temp, buf, len);
  }
  delay(30000); // 30 second measurement interval
}

Rust SDK Integration (Linux Example)

# Cargo.toml
[dependencies]
fidesinnova-zkp = "0.3"
tokio = { version = "1", features = ["full"] }

// main.rs
use fidesinnova_zkp::{ZKP, ProofInput};

#[tokio::main]
async fn main() {
  let zkp = ZKP::new("./proving_key.bin").await.unwrap();

  let input = ProofInput { temperature: 2240, timestamp: now_unix() };
  let proof = zkp.generate_proof(input).await.unwrap();
  let bytes = proof.serialize();
  // publish bytes + reading via MQTT...
}

AI ZKP Integration Agent

The ZKP Integration Agent is an AI tool that automates SDK integration into your existing firmware:

  1. Upload your firmware source code (or provide a GitHub URL)
  2. The agent analyzes your code structure and identifies sensor reading points
  3. It generates the modified firmware with ZKP calls inserted at the correct locations
  4. It generates a platformio.ini or Cargo.toml with SDK dependency added
  5. Review the diff, approve, and download the modified firmware
Security note: The agent processes your code server-side. For sensitive commercial firmware, use the agent on a sanitized test version and manually apply the identified integration pattern to your production code.

Proof Generation Flow

Understanding the internal flow helps with debugging and optimization:

1

Input Preparation (~5ms)

Sensor readings are converted to integer field elements (multiply floats by 100 or 1000 to preserve decimal precision as integers). Timestamp and device ID are included in the witness input.

2

Witness Computation (~180ms)

The SDK evaluates the compiled circuit on the inputs, computing all intermediate wire values. This is the most memory-intensive phase — the witness buffer is allocated in RAM.

3

Proof Computation (~500ms)

Three elliptic curve multi-scalar multiplications (MSM) on BN-128 curve compute the proof points A, B, C. This is the most CPU-intensive phase — the proving key (stored in flash) is streamed in chunks during this phase to minimize RAM usage.

4

Serialization (~2ms)

The three curve points are serialized to ~200 bytes using compressed point representation. The proof is ready for MQTT transmission.

Performance Optimization

  • Async proof generation — on RTOS platforms (FreeRTOS, Zephyr), run proof generation in a background task so sensor polling continues during the ~700ms proof computation
  • Proof batching — on high-frequency sensors (readings every second), generate a proof for every Nth reading (N=10 for 10-second effective proof frequency) to reduce CPU load without losing verifiability
  • Low-memory mode — if RAM is below 128KB, enable zkp.setLowMemoryMode(true) — proof generation takes ~2s but only uses 64KB RAM
  • Flash partition sizing — the proving key requires ~400KB of flash storage. Ensure your partition table allocates a dedicated NVS partition of at least 512KB
  • CPU frequency — on ESP32, setCpuFrequencyMhz(240) during proof generation reduces time by ~35% vs. 160MHz

Troubleshooting Common Issues

❌ "Proving key not found"

The proving key must be flashed to the device separately from the firmware binary. Use the FidesInnova CLI: fi-cli flash-key --port /dev/ttyUSB0

❌ "Witness computation failed"

Ensure all input values are within the circuit's valid range. The circuit expects integers in the range [0, 2³²]. Float readings must be scaled to integers before passing to generateProof().

❌ Proof rejected by Node

Mismatch between the device's proving key and the Node's verification key. Both must be from the same trusted setup ceremony. Re-download and re-flash the proving key from your Node dashboard.

❌ Out of memory crash

Enable low-memory mode or increase the heap allocation for the zkp object. On ESP32 with PSRAM, the SDK automatically uses external RAM for the witness buffer — enable PSRAM in menuconfig.

What You Will Learn

  • Understand the SDK architecture and supported platforms
  • Integrate the C++ SDK into ESP32 and ARM Cortex-M firmware
  • Use the Rust SDK for more complex embedded Linux targets
  • Use the AI ZKP Integration Agent for automatic SDK setup
  • Benchmark proof generation time on your target hardware
  • Troubleshoot common integration issues and optimize performance
🤖
AI Learning Assistant

Ask any question about this course topic

Ask AI ↗