# 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.