aere-docs/AERE-PQ-AGGREGATE.md
Aere Network e4cead319d Initial public release
Aere Network public source. Everything here can be checked against the live
chain (chain id 2800, https://rpc.aere.network).

Scope note, stated up front rather than buried: consensus on chain 2800 is
classical secp256k1 ECDSA QBFT. The post-quantum work in this repository is at
the signature, precompile, account and transport layers. Nothing here makes the
consensus post-quantum, and no document in it should be read as claiming so.
2026-07-20 01:01:36 +03:00

12 KiB

AerePQAggregate: constant-cost t-of-n post-quantum committee authorization

Status: on-chain verifier and ERC-7579 module BUILT and TESTED against a mock SP1 gateway. Off-chain SP1 aggregation circuit NOT implemented, [MEASURE], research frontier.

Scope: account and authorization layer only. This changes nothing about Aere Network consensus, which stays classical ECDSA QBFT. What is post-quantum here is the AUTHORITY that approves a message, not the block production.

Contracts:

  • contracts/contracts/mpc/AerePQAggregateVerifier.sol
  • contracts/contracts/modular/AerePQAggregateModule.sol
  • Test: contracts/test/AerePQAggregate.test.js (17 passing)

1. The problem this answers

NIST post-quantum signatures are large. An ML-DSA-65 signature is about 3,300 bytes, an ML-DSA-44 signature about 2,420 bytes, an SLH-DSA-128s signature about 7,856 bytes. A t-of-n committee that authorizes on-chain by supplying t independent PQC signatures therefore pays, on-chain, for t signature verifications plus t large calldata blobs. That cost is LINEAR in t and, under a per-transaction gas ceiling (Aere Network keeps Fusaka's EIP-7825 cap of 2^24 gas), it bounds how large a committee can practically authorize in one transaction. This is the same economic wall that motivates EIP-7932 (transaction-level signature abstraction for large or alternative signature schemes): post-quantum signatures do not fit the classical fixed-size signature budget.

AereThresholdPQCRegistry (already in this repo) takes the honest linear path: it verifies t INDEPENDENT PQC signatures on-chain through Aere Network's live precompiles. Every leg is a real NIST PQC signature, the t-of-n participation is proven on-chain, and the cost is linear in t.

AerePQAggregate takes the succinct path. It moves the t (up to n) signature verifications OFF the chain, into a zero-knowledge virtual machine (the SP1 zkVM), and verifies ONE small proof on-chain. The on-chain cost becomes INDEPENDENT of the committee size n.


2. The scheme

Off-chain (the SP1 aggregation circuit, [MEASURE], NOT implemented here)

A relying party commits, once, to a committee: a root (a binding commitment to the exact n authorized PQC public keys, for example a Merkle root over the canonically ordered keys or the keccak256 of the canonical key list), a threshold t, a size n, and a scheme.

To authorize a 32-byte messageDigest, an off-chain prover runs the aggregation guest program inside the SP1 zkVM with:

  • PRIVATE witness: the n committed public keys, and at least t PQC signatures over messageDigest.
  • The circuit MUST, inside the zkVM:
    1. recompute root from the witnessed keys (and abort if it does not match the committed root),
    2. verify each of the counted signatures against a DISTINCT committed key over messageDigest, using the scheme's real verification algorithm,
    3. never double-count a key (distinctness by committed index),
    4. output the PUBLIC values below.
  • PUBLIC output (the fixed 192-byte layout the on-chain verifier decodes): abi.encode(bytes32 committeeRoot, uint256 threshold, uint256 committeeSize, uint256 scheme, bytes32 messageDigest, uint256 validCount) where validCount is the number of distinct valid signatures the circuit verified, and must be at least threshold.

The proof is succinct: its size and its on-chain verification cost are fixed by the SP1 verifier, independent of n and of how many signatures the circuit checked internally.

On-chain (BUILT and TESTED here)

AerePQAggregateVerifier:

  1. registerCommittee(root, t, n, scheme) stores the committee. The n public keys are NOT stored on-chain (storing them would reintroduce the O(n) cost the design removes); root is the sole on-chain commitment to them. Permissionless, no admin, holds no funds.
  2. verifyAggregate(committeeId, messageDigest, publicValues, proofBytes) binds the proof's public values to the registered committee and to the caller's claimed message, then makes a SINGLE verifyProof call to the deployed SP1 verifier gateway. It is fail-closed: it rejects unless ALL hold:
    • the committee is registered,
    • publicValues.committeeRoot == committee.root (the sole authority binding),
    • publicValues.threshold / committeeSize / scheme == committee.{threshold,size,scheme} (defense in depth),
    • publicValues.messageDigest == messageDigest (the caller's claimed message),
    • publicValues.validCount >= committee.threshold,
    • the SP1 proof verifies against the pinned circuit vkey (verifyProof REVERTS on an invalid proof).
  3. tryVerifyAggregate(...) is the non-reverting variant (returns bool) used by the ERC-4337 and ERC-7579 validation paths, which SHOULD return a failure code rather than revert.
  4. recordAggregate(...) verifies (strict) and records an on-chain provenance attestation.

The circuit is pinned. AGGREGATE_PROGRAM_VKEY is fixed at construction, so a registrant cannot substitute a different circuit: every committee is proven by the same audited program through the same immutable gateway. Deploy one verifier per circuit (for example one for the ML-DSA-65 aggregation program).

The deployed SP1 verifier gateway on Aere Network mainnet (chain 2800) is the canonical Succinct gateway at 0x9ca479C8c52C0EbB4599319a36a5a017BCC70628, the same gateway the parallel-execution validity contracts and the zk light clients already call.


3. The gas argument: constant vs linear in n

The verifier does NO per-member work on-chain. There is no loop over keys, no per-signature precompile call, no per-member calldata. It reads a fixed committee record, compares six words of public values, and makes one verifyProof call. The cost is therefore fixed by the SP1 verifier and independent of n.

Measured in the test suite (recordAggregate, mock gateway):

committee size n gas used
5 61,799
1,000,000 61,823

n grew by 200,000x; gas moved by 24 (the calldata encoding of the larger integer, which is O(log n), not O(n)). A linear on-chain t-of-n PQC verifier pays tens of thousands of gas PER signature (the marginal precompile verify cost for ML-DSA-44 is about 55,000 gas, before calldata), so at even a modest committee it hits the per-transaction gas ceiling; the aggregate path does not.

(The gas figures above are for the mock gateway. The REAL SP1 Groth16/Plonk verifier is more expensive per call but still CONSTANT in n; the constant-vs-linear conclusion is what the on-chain design guarantees. The absolute real-gateway number is [MEASURE].)


4. ERC-4337 and ERC-7579 portability

The authorization is exposed two ways.

  • ERC-4337 authorization path. messageDigest is the userOpHash, so the aggregate proof is bound to one exact operation. The account nonce inside the userOpHash makes the authorization non-replayable at the account layer, so the verifier itself needs no separate replay nonce.

  • ERC-7579 validator module. AerePQAggregateModule implements the type-1 validator surface from the ERC-7579 standard (OpenZeppelin interfaces/draft-IERC7579.sol IERC7579Validator): onInstall / onUninstall / isModuleType, validateUserOp(PackedUserOperation, bytes32) returning the ERC-4337 code (0 success, 1 failure), and isValidSignatureWithSender(address, bytes32, bytes) returning the ERC-1271 magic value 0x1626ba7e on success. An account is bound to a committee at install time; the module then validates each userOp (and each ERC-1271 signature) by asking the verifier whether the committee signed the digest. Both paths are fail-closed and never revert on a bad or malformed signature, per the validator SHOULD.

Because ERC-7579 is a chain-agnostic modular-account standard, the SAME module can be installed on a Safe (via the Safe7579 adapter), a Kernel, or a Nexus account on ANY EVM chain, and the verifier it points at can be deployed on that chain against that chain's SP1 gateway. The rule "a t-of-n post-quantum committee approved this userOp" then travels with the account across chains.

[VERIFY] The module assumes the account has already stripped any validator-routing prefix (ERC-7579 stacks select the validator by an address carried in the userOp nonce key, or in some stacks a prefix on the signature) before calling the module, matching the OpenZeppelin AccountERC7579 dispatcher. Confirm the exact unwrapping and the PackedUserOperation field layout against the specific account implementation you deploy under (Safe7579 / Kernel / Nexus).


5. Bank28 custody use case

Bank28 is a non-custodial neobank stack. A treasury or custody account can be governed by a t-of-n committee of post-quantum keys (for example 3-of-5 ML-DSA-65 signers held on separate HSMs or devices). With AereThresholdPQCRegistry the account pays on-chain for t independent PQC verifications each time it moves funds, and the committee size is bounded by the per-transaction gas ceiling. With AerePQAggregate:

  • the committee can be large (institutional custody often wants a big quorum: many independent approvers, several of them offline) because on-chain cost does not grow with n,
  • each fund movement is one small proof, so gas and calldata are predictable and flat,
  • the account is a standard ERC-7579 modular account with the validator module installed, so it works with existing bundler and wallet infrastructure and is portable across the chains Bank28 settles on,
  • the authority is quantum-durable: a quantum adversary that can forge ECDSA still cannot authorize a movement without the committee's PQC private keys, because the underlying legs are NIST PQC signatures proven in the zkVM.

Scope note: this authorizes ACCOUNT actions. It is not custody advice and it does not make Aere Network consensus post-quantum. Bank28 must still follow its lawful KYC/AML obligations; this is an authorization primitive, not a compliance control.


6. Honest status

BUILT and TESTED (this repo):

  • AerePQAggregateVerifier.sol: committee registry, public-input binding scheme, fail-closed strict and non-reverting verification, constant-cost single verifyProof call, provenance recording.
  • AerePQAggregateModule.sol: ERC-7579 type-1 validator module wrapping the verifier for the ERC-4337 and ERC-1271 paths.
  • 17 passing Hardhat tests against MockSp1Verifier, the same deployed-gateway test double used by AereComputeMarketV3 and the zk light clients. Its verifyProof REVERTS on an invalid proof, so the fail-closed path is exercised exactly as against the production gateway. Tests cover: a valid proof authorizes; an invalid proof rejects fail-closed; a wrong-message-digest proof rejects; a wrong-committee-root proof rejects; below-threshold rejects; threshold/size/scheme mismatch and malformed public values reject; unknown committee rejects; gas is constant across n = 5 vs n = 1,000,000; and the module returns the correct ERC-4337 code and ERC-1271 magic value on valid inputs and fails closed (without reverting) on invalid or malformed ones.

NOT implemented, [MEASURE], research frontier:

  • The OFF-CHAIN SP1 aggregation guest circuit. Verifying n PQC signatures against the committee root inside a zkVM and emitting the public values is real cryptographic engineering that is NOT in this repository. The on-chain verifier is proven against a mock gateway that asserts the bound public values; a real end-to-end system additionally needs the real circuit and a real SP1 proof.
  • Verifying Falcon inside a zkVM is HARD: Falcon signature verification touches FFT over the ring and, in reference implementations, floating-point Gaussian sampling paths, which are expensive and delicate to make deterministic and constraint-friendly in a zkVM. ML-DSA (FIPS 204, Dilithium lineage) is integer-arithmetic and modular-reduction based, with no floating point, so ML-DSA-65 aggregation is the TRACTABLE FIRST TARGET. The pinned scheme constant in the verifier reflects this (SCHEME_MLDSA65 = 5). A Falcon aggregation circuit is a later, separate verifier deployment with its own pinned vkey.
  • The real end-to-end proving cost and latency, and the real-gateway on-chain verify gas, are [MEASURE] and depend on the circuit implementation.

Do NOT claim the aggregation works end-to-end. The claim that IS supported by this repository: the on-chain verification and portability rail is built and fail-closed, and its cost is provably constant in the committee size n.