CRUMB a card from devarno-cloud

FNP WASM & Server-Side Proof Verification

fnp advanced 7 min read

ELI5

Mobile phones are slower than servers. FNP gives mobile users two choices: verify proofs locally (5-16ms, private) or let the server verify (1.2ms, faster but requires trust). FNP also caches verified proofs (5-minute TTL) so users don’t verify the same proof twice.

Technical Deep Dive

Mobile Latency Breakdown

OperationServer (ms)Mobile WASM (ms)Ratio
Kyber encapsulation0.8ms8-12ms10-15x
M²-ORE encryption0.3ms3-5ms10-17x
Halo2 proof verification1.2ms16ms13x
Dilithium verification0.5ms6ms12x
Total insert operation~50ms400-600ms8-12x

Halo2 Proof Verification: Mobile vs Server

Mobile (local verification):

1. Download proof (514 bytes) + operation data
2. WASM deserialization (2ms)
3. IPA verification (16ms)
4. Constraint evaluation (4ms)
5. Result: proof is valid or invalid
Total: 22ms (verified locally, no trust in server)

Server (delegated verification):

1. Server generates proof on INSERT
2. Client receives: operation_id + "proof verified by server"
3. Client verifies: server signature on (operation_id, proof_hash)
4. Result: proof was verified by server (~1.2ms earlier)
Total: 2-3ms (trusts server, faster)

Proof Caching (5-minute TTL)

Scenario: Same edit operation on 100 mobile users

Without caching:

100 users * 16ms = 1600ms total verification time
100 users see latency: ~50-100ms (includes verification)

With caching:

User 1: Proof generated on server, cached with key=hash(operation_id, proof_data)
User 2-100: Cache hit, server returns "proof_id=xyz (verified 4 minutes ago)"
100 users * 0.1ms = 10ms total verification time
100 users see latency: ~5-10ms (cache lookup only)
Savings: 90%+ latency reduction

WASM Module Design

FNP’s WASM module exposes:

src/wasm/frust_lib.rs
#[wasm_bindgen]
pub fn verify_halo2_proof(proof: &[u8], public_inputs: &[u8]) -> bool {
// Halo2 proof verification
// Returns true/false
}
#[wasm_bindgen]
pub fn kyber_encapsulate(public_key: &[u8]) -> EncapsulationResult {
// Returns (ciphertext, shared_secret)
}

WASM bundle size:

  • Halo2 verification: 850KB
  • Kyber: 200KB
  • M²-ORE: 150KB
  • Total: ~1.2MB (gzipped: 300KB)

Loaded at app startup: First load 300KB; thereafter cached locally.

Trustless vs Delegated Verification

Trustless (mobile verifies):

  • Client: verify proof locally
  • Trust model: only you
  • Latency: 16ms
  • Privacy: server learns nothing

Delegated (server verifies):

  • Client: trust server’s “proof verified” claim
  • Trust model: trust server + TLS + Dilithium signature on claim
  • Latency: 1-2ms
  • Privacy: server knows operation happened (learns metadata)

FNP recommendation:

  • Critical edits (sensitive documents): verify locally (16ms)
  • Regular edits (collaborative): use delegated (1-2ms)
  • User can toggle per-session

Key Terms

  • WASM (WebAssembly) → Binary format for browser/mobile execution; ~10-100x faster than JavaScript
  • Proof caching → Storing verified proofs by hash; reuse within 5-min window
  • Delegated verification → Client trusts server’s proof verification claim (faster)
  • Trustless verification → Client independently verifies (slower, private)

Q&A

Q: Why not just offload all cryptography to server? A: Privacy. If server verifies all proofs, server learns patterns (who edits what, when). Trustless mobile verification preserves privacy; delegated is opt-in for performance.

Q: Does WASM work on all phones? A: iOS Safari doesn’t support WASM as of 2026, but Android Chrome, Firefox, Edge all support it. iOS users fall back to delegated verification.

Q: Can old cached proofs become invalid? A: Yes, if keys rotate (1-year Kyber rotation). Cached proofs > 1 year old are auto-expired. Cache hit rate optimized for 5-min window.

Examples

WASM on mobile is like having a small calculator vs calling an accountant: you can calculate yourself (slow, private) or ask accountant (fast, but you trust them).

neighbors on the map