Testnet live · VFRI8 Phase 1 complete · Poseidon2 trace commitment · ≤15M gas · security audit 2026-06-10

Build the post-quantum migration layer before it becomes urgent

QLSA aggregates thousands of post-quantum signatures into a single constant-size proof, targeting scalable blockchain verification without trusted setup and without forcing a hard fork.

QLSA (Quantum-Layered Signature Aggregation) is an open deep-tech project exploring how ML-DSA, Merkle commitments, and STARK proofs can make post-quantum blockchain systems operationally viable.

FocusInfrastructure, not just cryptography
CI847 Solidity + 528 Python + 210 Rust + 71 TS — all green
StatusPhase 6 ✓ · VFRI7 ✓ · VFRI8 ✓ · security & code audit 2026-06-10

What's been built

Phase 6 complete — live on Ethereum Sepolia (2026-05-05). V23 production pipeline: 8 ML-DSA circuits in 1 STARK proof (3,505 trace columns). MVP-4 complete (2026-05-22): QLSAVerifierVFRI6 — O(1)-gas on-chain FRI verifier. MVP-5 complete (2026-05-30): QLSAVerifierVFRI7 + BatchRegistryV4 dual-VFRI7 — cross-proof binding (keccak256(batchRoot ‖ traceRoot)) prevents proof-mixing attacks. VFRI8 Phase 1 complete (2026-06-10): QLSAVerifierVFRI8 — Poseidon2 Merkle trees + Poseidon2 Fiat-Shamir channel — 20-query on-chain FRI verification ≤15M gas on Ethereum mainnet. BatchRegistryV5 dual-VFRI8. Security & code audit (2026-06-10): 7 fixes across 5 files; 3 crypto findings, 4 systems findings. 847 Solidity + 528 Python + 210 Rust + 71 TS tests — all CI green.

Security & code audit (2026-06-10)7 fixes: VFRI8 OODS division-by-zero guard, num_folds cross-bound param (C2), short-proof calldataload guard in BatchRegistryV4/V5 (C3), API rate limit on /stats+/config (H2), VFRI8 witness_commitment fallback (H5), _sender_txs eviction sync (M6), dead _call_prover function removed (C1). 528 Python + 210 Rust + 71 TS tests green.
VFRI8 Phase 1 — Poseidon2 trace commitment (2026-06-10)QLSAVerifierVFRI8: Poseidon2 Merkle trees + Poseidon2 Fiat-Shamir channel (Poseidon2Channel.sol, Poseidon2MerkleVerifier.sol). 20-query on-chain FRI verification ≤15M gas: 20 × 2 paths × depth=10 × ~1000 gas/permute ≈ 400K gas (Merkle) + ~5M (rest). BatchRegistryV5 dual-VFRI8 with identical cross-proof binding.
Code audit (2026-06-03)HttpClient._decode_json() guards all 7 JSON call-sites — proxy HTML responses (nginx 2xx) no longer crash the SDK. testnet/e2e.py sender_key recomputation eliminated; unused import hashlib removed. 239 Python tests green.
Cryptographic coreML-DSA-65/44/87, SHA3-512 Merkle, address derivation, pubkey validation, batch aggregation
STARK prover (Stwo 2.2.0) — V23Circle STARK, Poseidon2-over-M31 AIR, 8 ML-DSA circuits in 1 FRI commitment (3,505 trace columns): NttBatch + AzFull + Ct1Full + InttBatch + WPrimeFull + NormCheck + UseHintV2 + RangeQBatch (az_hat ∈ [0,Q))
Smart contracts — deployed SepoliaBatchRegistryV2/V3/V4/V5 (nonce replay protection, MAX_SENDERS DoS cap), QLSAVerifierFull + VFRI7 + VFRI8 (O(1)-gas FRI, cross-proof binding, Poseidon2 Merkle), 847 Solidity tests
Aggregator node + APIThread-safe mempool (atomic drain), auto-batcher, FastAPI REST, rate limiting (100 tx/min per IP, proxy-aware), pk/sig length validation
SDKs (Python + TypeScript)Wallet, LocalClient + HttpClient, WitnessStatus, TypeScript AggregatorClient — mypy strict
Testnet E2E (Sepolia, 2026-05-05)First batch: 4 tx, 3234-byte proof, 9.16 s finalization. submitBatchWithNonces on-chain.
On-chain FRI verifier library stackCM31 · QM31 · Blake2sYul · MerkleVerifier · TwoChannel · CirclePoint · QLSAVerifierV4–V13 · VFRI/VFRI2/VFRI3/VFRI4/VFRI5/VFRI6 — full K-round FRI + OODS + composition tree + O(1)-gas off-chain OODS combo
Security audit round 1 (2026-05-22)Constant-time Merkle (hmac.compare_digest), rate-limit thread-safety, MAX_SENDERS=3000 DoS cap (O(n²) loop), y=0 circle guard (M31.inv panic), _MAX_HISTORY=1000 memory cap, PRIVATE_KEY env fallback
BatchRegistryV4 — dual-VFRI7 (2026-05-30)Requires both LOG=10 (1298 cols) and LOG=8 (2206 cols) VFRI7 proofs. Cross-proof binding: boundRoot10 = keccak256(batchRoot ‖ traceRoot8) — mixing proofs from different witnesses fails Merkle verification
Security audit round 2 (2026-05-30)O(1) batch history (deque + dict index, eliminates O(n) scan DoS), N_FRI_QUERIES range validation, IP address validation for TRUSTED_PROXIES, ML-DSA pubkey size guard, UUID input validation, GET /batch/* rate limit, module-level logger — 24 total findings resolved

The Problem

Direct migration from classical signatures to post-quantum signatures can severely inflate block payloads. That turns protocol safety progress into an operational scaling problem.

Signature Size 3000 tx block Operational impact
ECDSA (current)~70 bytes~220 KBFits today's assumptions
ML-DSA-65 (FIPS 204)~2,420 bytes~7.2 MBSevere throughput penalty
~30–40×Payload overhead from direct migration
FIPS 204Standardized signature base
Hash-firstNo trusted setup in the proving path
L2-readyDeployment path without hard fork

The Solution

QLSA is not a new signature scheme. It is a post-quantum aggregation layer that aims to make large signature sets proof-friendly, compact, and verifiable at fixed on-chain cost.

What QLSA does

  • Aggregates N ML-DSA signatures into one batch commitment
  • Uses Merkle commitments to structure batch data
  • Generates a STARK proof for batch correctness
  • Allows fixed-cost on-chain verification independent of batch size

Why the architecture matters

  • Heavy proving remains off-chain
  • Public inputs can be kept minimal with commitment roots
  • MVP can ship before full ML-DSA-inside-AIR is solved
  • The system remains crypto-agile across future upgrades

Architecture

The system is split into three layers so that user flows stay familiar, proving stays off-chain, and on-chain verification remains lean.

Layer 1

Signing

Wallet-level signing using post-quantum keys.

  • ML-DSA-65 for signatures
  • Address derived from SHA3-256(pubkey)
  • Intended to preserve a familiar wallet-style UX
Layer 2

Aggregation

Batch formation and proving pipeline.

  • Collect transactions off-chain
  • Verify ML-DSA signatures off-chain; V23 proves arithmetic witness (8 circuits) inside STARK
  • Build Merkle tree with SHA3-512; root bound into Fiat-Shamir channel (V22+)
  • Generate STARK proof — c̃ + merkle_root mixed; RangeQBatch proves az_hat ∈ [0,Q)
Layer 3

Verification

Constant-cost contract-side validation.

  • Verify proof in Solidity verifier contract
  • Store merkle_root and finalize the batch
  • onchain_commitment = Blake2s(proof[:32] ∥ c_tilde[:32])[:16] — 128-bit binding
  • MVP-6: VFRI8 — Poseidon2 Merkle + Fiat-Shamir channel; 20-query verification ≤15M gas. Both LOG=10 and LOG=8 trace groups verified on-chain with 130-bit soundness.

MVP Strategy

The project intentionally separates realistic implementation milestones from the hardest research component.

StageWhat STARK provesML-DSA in STARKStatus
MVP-1Core crypto & MerkleNo✓ Done
MVP-2Hash-chain + Poseidon2 AIR (Stwo)No✓ Done
MVP-2bML-DSA batch proof (Rust + STARK)Off-chain✓ Done
MVP-3+All 8 circuits inside AIR + RangeQBatch (V23)Yes (V23)✓ Complete
MVP-4VFRI4/5/6 — O(1)-gas on-chain FRI verifier; BatchRegistryV4Yes✓ Done (2026-05-22)
MVP-5VFRI7 cross-proof binding; security audit round 2; code quality hardeningYes✓ Done (2026-05-30)
MVP-6VFRI8: Poseidon2 Merkle + channel; 20-query ≤15M gas; BatchRegistryV5; security & code auditYes✓ Done (2026-06-10)

Key risks

  • ML-DSA inside STARK: All 8 circuits complete in V23 (NttBatch + AzFull + Ct1Full + InttBatch + WPrimeFull + NormCheckBatch + UseHintBatchV2 + RangeQBatch), 3,505 trace columns, 1 FRI commitment. c̃ + Merkle root Fiat-Shamir bound; RangeQBatch closes AzFull multiplication soundness gap.
  • Aggregator trust model: the MVP relies on off-chain verification before challenge systems exist.
  • Adoption timing: the need is real, but mainstream migration may still take years.
Research-driven Benchmark-first Security-aware

Tech Stack

The technical stack reflects a staged path: fast iteration now, stronger proving infrastructure later.

Cryptographic core

  • ML-DSA-65
  • SHA3-512 for Merkle hashing
  • SHA3-256 for address derivation
  • Python 3.10+
  • liboqs-python >= 0.14.0

STARK layer

  • Stwo 2.2.0 — Circle STARK over M31 field
  • Poseidon2-over-M31 AIR (t=2, α=5, 8 full rounds, 7 columns, 6 constraints ≤ deg 3)
  • V23 single STARK: 8 ML-DSA circuits, 3,505 trace columns, 1 FRI commitment
  • ML-DSA-65 FIPS 204 verifier in Rust; c̃ + Merkle root Fiat-Shamir binding
  • FRI blowup ×64, N_FRI_QUERIES=20, POW_BITS=10 — 130-bit soundness; zeroize crate for secure key wipe
  • nightly-2025-07-01 Rust toolchain

Contracts & infra

  • Solidity + Hardhat 2.28
  • VFRI8 verifier stack: CM31 · QM31 · Blake2s · Poseidon2M31 · Poseidon2MerkleVerifier · Poseidon2Channel · CirclePoint · QLSAVerifierVFRI8
  • BatchRegistryV5 — dual-VFRI8 with cross-proof binding
  • FastAPI aggregator + rate limiting (proxy-aware, stale eviction)
  • Python SDK (Wallet, LocalClient, WitnessStatus) + TypeScript SDK

Performance targets

Batch size3,000 tx
Proof size90–200 KB
On-chain verificationO(1)
ML-DSA-65 sign (avg)0.12 ms / tx
Merkle build N=30007.1 ms
Full pipeline N=3000354 ms
V23 STARK columns3,505 (649+1523+295+649+24+15+61+288+1 preproc)
20-query VFRI8 gas≤15M gas (Poseidon2 Merkle ~10K gas/path vs ~800K for Blake2s)
Solidity tests847 passing
Python tests528 passing (with PyO3) / 336 without
Rust tests210 passing
TS tests71 passing
CI pipeline5 / 5 jobs green

Repository snapshot

QLSA/
├── core/          # ML-DSA, Merkle, batch
├── aggregator/    # Mempool, batcher, FastAPI
├── stark/         # Python prover/verifier wrappers
├── stark_stwo/    # Stwo STARK + ML-DSA AIR circuits
├── contracts/
│   └── src/verifier/
│       ├── CM31.sol       # GF((2³¹−1)[i])
│       ├── QM31.sol       # quartic extension
│       ├── Blake2s.sol    # pure-Solidity
│       ├── Poseidon2M31.sol      # t=2 over M31
│       ├── Poseidon2MerkleVerifier.sol
│       ├── Poseidon2Channel.sol  # Fiat-Shamir
│       ├── MerkleVerifier.sol
│       ├── TwoChannel.sol # Fiat-Shamir (Blake2s)
│       └── CirclePoint.sol # CanonicCoset + FRI fold
├── sdk/python/    # Wallet, LocalClient
├── sdk/js/        # TypeScript AggregatorClient
├── testnet/       # E2E demo, deploy, submit
└── tests/         # 847 Sol + 528 Py + 210 Rust + 71 TS

Roadmap

The roadmap prioritizes a credible implementation path before expanding into the hardest proving research.

Phase 1 — Core

✓ Complete

ML-DSA-65/44/87 keys, signing, transaction model, SHA3-512 Merkle tree, batch aggregation.

Phase 2 — STARK Prototype

✓ Complete

Stwo 2.2.0 Circle STARK — Poseidon2-over-M31 AIR (t=2, α=5, 8 full rounds, 7 main columns, 4 preproc columns, 6 constraints ≤ deg 3), ML-DSA-65 batch verifier in Rust (FIPS 204), FRI blowup ×4. 128-bit Blake2s commitment. 210 Rust tests green.

Phase 3 — Smart Contracts

✓ Complete

QLSAVerifierFull, QLSAVerifierBound (Merkle-root-bound Blake2s, bytes16 128-bit commitment), BatchRegistry, BatchRegistryV2 — all deployed (Hardhat). Contract tests green.

Phase 4 — Aggregator Node

✓ Complete

In-memory mempool (thread-safe, atomic drain), auto-batcher with transaction recovery, FastAPI REST endpoint. Full STARK prove→submit pipeline via PyO3 native FFI.

Phase 5 — SDK

✓ Complete

Python SDK (wallet + async client) and TypeScript/JavaScript SDK with full input validation and typed API. wipe_key() backed by Rust zeroize crate (volatile writes) for secure key wipe.

Phase 6 — Testnet

✓ Complete

Live on Ethereum Sepolia (2026-05-05). QLSAVerifierBound: 0xF2dcad845F0fb4a11106E4c4cF23D260a3CB65Dd · BatchRegistryV2: 0xF44A51CF1d7620e070ecaf611685418DE4679879. First batch: tx 0x5a9215d2aeb4…bd82, 3234 bytes, finalized in 9.16 s. Security hardening: nonce registry, rate limiting, pubkey validation.

MVP-3+ — ML-DSA Native in AIR (V22/V23)

✓ Complete

All 8 ML-DSA-65 arithmetic circuits unified in one FRI commitment (V23, 3,505 trace columns): NttBatch (LOG=10, 649 cols) + AzFull (LOG=8, 1523 cols) + Ct1Full (LOG=8, 295 cols) + InttBatch (LOG=10, 649 cols) + WPrimeFull (LOG=8, 24 cols) + NormCheckBatch (LOG=8, 15 cols) + UseHintBatchV2 (LOG=8, 61 cols + 1 preproc) + RangeQBatch (LOG=8, 288 cols). Fiat-Shamir transcript: c̃ → merkle_root → Tree0 → Tree1. RangeQBatch closes AzFull multiplication soundness gap.

MVP-4 — Mainnet-grade On-chain Verifier

✓ Complete (2026-05-22)

Full on-chain Circle STARK FRI verifier (Solidity). Verifier library stack: CM31 · QM31 · Blake2sYul · MerkleVerifier · TwoChannel · CirclePoint · QLSAVerifierV4–V13 · VFRI–VFRI6. QLSAVerifierVFRI6: O(1)-gas off-chain OODS combo — 649, 1298 and 2206-column traces all verified within 15M gas. BatchRegistryV4: dual-VFRI6 registry.

MVP-5 — Cross-Proof Binding & Security Hardening

✓ Complete (2026-05-30)

QLSAVerifierVFRI7: adds mixRoot(merkleRoot) before drawQueries — FRI query indices depend on the batch Merkle root, preventing proof-mixing attacks. BatchRegistryV4 updated: boundRoot10 = keccak256(batchRoot ‖ traceRoot8) / boundRoot8 = keccak256(batchRoot ‖ traceRoot10) — cross-binding both LOG groups. Security audit round 2: 24 findings resolved. Code audit 2026-06-03: HttpClient._decode_json() + e2e.py sender_key. 847 Solidity + 239 Python + 210 Rust + 39 TS tests — all CI green.

MVP-6 — VFRI8: Poseidon2 Trace Commitment

✓ Complete (2026-06-10)

QLSAVerifierVFRI8: replaces Blake2s Merkle trees and Fiat-Shamir channel with Poseidon2-over-M31 — 20-query on-chain FRI verification fits within 15M gas on Ethereum mainnet (vs ~300M gas with Blake2s). Gas breakdown: 20 queries × 2 paths × depth=10 × ~1000 gas/permute ≈ 400K gas (Merkle) + ~5M (rest) ≈ 5.4M total. BatchRegistryV5: dual-VFRI8 registry with identical cross-proof binding logic (keccak256(batchRoot ‖ traceRoot)). Commitment format unchanged: Blake2s(proof[:32] ∥ merkleRoot)[:16]. Security & code audit 2026-06-10: 7 fixes — VFRI8 OODS division-by-zero guard, cross-bound num_folds param, BatchRegistryV4/V5 short-proof calldataload guard, API rate limit on /stats+/config, VFRI8 witness_commitment fallback, _sender_txs eviction sync. 847 Solidity + 528 Python + 210 Rust + 71 TS tests — all CI green.

FAQ

Short answers to the questions most people will ask when they first encounter the project.

Is QLSA a new signature algorithm?

No. QLSA is an aggregation and verification architecture built around post-quantum signatures such as ML-DSA.

Why not just replace ECDSA directly?

Because the size increase of post-quantum signatures can cause major throughput and cost problems if deployed naively.

Does QLSA already prove ML-DSA inside STARK?

Yes — V23 is the production pipeline. All 8 ML-DSA-65 arithmetic circuits are unified in one FRI commitment (3,505 trace columns): NttBatch + AzFull + Ct1Full + InttBatch + WPrimeFull + NormCheckBatch + UseHintBatchV2 + RangeQBatch. c̃ and batch Merkle root are both mixed into Fiat-Shamir, binding each proof to one specific witness and batch.

What on-chain verifier exists?

MVP-6 (2026-06-10): QLSAVerifierVFRI8 + BatchRegistryV5 (dual-VFRI8). Poseidon2 Merkle trees + Poseidon2 Fiat-Shamir channel — 20-query on-chain FRI verification ≤15M gas (Poseidon2 Merkle path ~10K gas vs ~800K gas for Blake2s). Both LOG=10 (1298 cols) and LOG=8 (2206 cols) trace groups verified within 15M gas with 20 queries. On-chain soundness: LOG_BLOWUP=6 × N_FRI_QUERIES=20 + POW_BITS=10 = 130-bit ✓ (matches off-chain prover config).

Is this production-ready?

No. QLSA is research-stage software (not audited by external parties). Infrastructure is fully implemented and tested (847 Solidity + 528 Python + 210 Rust + 71 TS tests). Not recommended for production use or real funds.

Interested in PQC, ZK proofs, or blockchain infrastructure?

QLSA is an open research and engineering effort. Contributions, technical feedback, research discussion, and collaboration are welcome.