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.
208 lines
14 KiB
Markdown
208 lines
14 KiB
Markdown
# AerePQ-Screen: an institution-grade post-quantum compliance passport
|
|
|
|
AerePQ-Screen upgrades Aere Network's compliance stack so it interoperates with the identity
|
|
standards banks and regulated institutions already use, W3C Verifiable Credentials 2.0, Decentralized
|
|
Identifiers (DID), and the ERC-3643 / ONCHAINID accreditation model, and adds the differentiator no
|
|
other stack carries today: issuer attestations that are POST-QUANTUM signed (Falcon-512) and verified
|
|
in full on-chain via Aere's live precompile at 0x0AE1.
|
|
|
|
It is built ON the existing compliance contracts (AereZKScreen, AereCompliancePool, AereSanctionsRegistry,
|
|
AereTravelRuleHashRegistry, and the live AerePQCKeyRegistry), not in place of them. It adds three new
|
|
contracts under `aerenew/contracts/contracts/compliance/` and does not modify any deployed contract.
|
|
|
|
## Honest status (read this first)
|
|
|
|
- CONTRACTS: built and tested. Three new Solidity 0.8.23 contracts, 12 passing Hardhat tests
|
|
(`test/aere-pq-screen.test.js`), verified against the repo's MockPQCPrecompile at 0x0AE1 exactly as
|
|
the erc8004 and PQC test suites do.
|
|
- POST-QUANTUM SIGNATURE PATH: real. Issuer attestations are Falcon-512 signatures verified on-chain
|
|
through the live AerePQCKeyRegistry, which routes to precompile 0x0AE1 (live on chain 2800,
|
|
activation block 9,189,161). The local test exercises this via the faithful mock; the real
|
|
precompile is separately proven against live mainnet via eth_call, as the rest of the PQC stack is.
|
|
- ZK NON-REVOCATION CIRCUIT: **[MEASURE]**. The on-chain W3C Bitstring Status List, the verifier
|
|
interface, the public-input shape, and the freshness binding are all built and tested. The SP1
|
|
circuit that actually produces a zero-knowledge non-revocation proof is NOT yet implemented. It is
|
|
to be built on Aere's existing SP1 zk stack (the same stack behind AereZKScreen).
|
|
- CONSENSUS SCOPE: unchanged. Aere consensus stays classical secp256k1 ECDSA QBFT. What is
|
|
post-quantum here is the AUTHENTICITY of compliance attestations, an application-layer property.
|
|
- ADOPTION AND ACCREDITATION: NOT claimed. Whether any real institution issues credentials here, and
|
|
whether accreditation in this registry carries legal weight under eIDAS 2.0 or any regime, is a
|
|
partnership and regulatory matter external to this code. Deploying these contracts asserts none of
|
|
it. This document describes what the code does, not who uses it.
|
|
|
|
## Architecture
|
|
|
|
The flow is Trust Registry, then VC issuance, then Bitstring status, then zk non-revocation.
|
|
|
|
```
|
|
Aere Foundation (trusted-list operator, registry owner)
|
|
|
|
|
| accredits issuers (scope + Falcon key ref)
|
|
v
|
|
AereTrustRegistry ----- verifyIssuerSignature() -----> AerePQCKeyRegistry (LIVE)
|
|
federated set of verifyWithKey() --> 0x0AE1 Falcon-512
|
|
accredited issuers (in-full on-chain PQC verify)
|
|
|
|
|
| isAccredited(issuerId, type)
|
|
v
|
|
AereVerifiableCredential ---- statusOf(list, index) ----> AereBitstringStatusList
|
|
W3C VC 2.0 anchor + verify: W3C Bitstring Status List
|
|
1. issuer accredited? revocation / suspension bitset
|
|
2. Falcon-512 issuer signature valid? (via 0x0AE1) + zk non-revocation verifier
|
|
3. within validity window? interface + public-input shape
|
|
4. not revoked? (status list bit == 0) (SP1 circuit = [MEASURE])
|
|
```
|
|
|
|
### 1. AereTrustRegistry (federated accredited issuers)
|
|
|
|
Trust is not a single Foundation key. It is a federated SET of accredited issuers, each with a DID,
|
|
an accreditation scope (which credential types it may issue), a lifecycle status, and an optional
|
|
Falcon-512 key reference. This mirrors, in spirit, the eIDAS 2.0 / EUDI trusted-list model, in which
|
|
a supervisory body maintains a machine-readable list of trust service providers and the services each
|
|
is accredited for. Here the Foundation is the trusted-list operator (the registry owner).
|
|
|
|
- Each issuer entry: `controller` (the issuer id / address), `did` (a did:aere DID, a public
|
|
identifier and not PII), accreditation `scope` (a set of opaque bytes32 credential-type tags),
|
|
`status` (Active / Suspended / Revoked), and `pqcKeyId` (an optional Falcon-512 keyId in the live
|
|
AerePQCKeyRegistry, sentinel `NO_KEY` when absent).
|
|
- FAIL-CLOSED: `isAccredited(issuerId, type)` is true only when the issuer is Active and the type is
|
|
in scope. Unknown, suspended, and revoked issuers, and out-of-scope types, all resolve to false.
|
|
- APPEND-ONLY HISTORY, NO SILENT REWRITE: every status transition and scope change is pushed to an
|
|
append-only log. The current status is a pointer; how it got there is immutable and auditable.
|
|
- TERMINAL REVOCATION: accreditation revocation cannot be reversed; suspension can.
|
|
- `verifyIssuerSignature(issuerId, message, sig)` verifies a Falcon-512 issuer attestation over a
|
|
32-byte message via the live AerePQCKeyRegistry (which calls precompile 0x0AE1), fail-closed.
|
|
|
|
### 2. AereVerifiableCredential (W3C VC 2.0 anchor + verify)
|
|
|
|
A credential binds an accredited `issuerId`, a subject `did:aere` DID (bound by its hash; the DID
|
|
string is carried off-chain, no PII on chain), a `credentialType`, a validity window (`validFrom` /
|
|
`validUntil`, the W3C VC 2.0 member names), a W3C BitstringStatusListEntry (`statusListId` +
|
|
`statusIndex`), and a `claimsHash` (keccak256 of the off-chain credentialSubject claims, so the anchor
|
|
commits to content without publishing it).
|
|
|
|
Verification (`verifyPresented`, and the live `isValid` for anchored credentials) checks, fail-closed:
|
|
|
|
1. the issuer is ACCREDITED for the credential type (AereTrustRegistry);
|
|
2. the issuer's Falcon-512 signature over the credential digest verifies on-chain via 0x0AE1;
|
|
3. the credential is WITHIN its validity window (not-yet-valid and expired both fail);
|
|
4. the credential is NOT REVOKED per its Bitstring Status List entry.
|
|
|
|
`anchorCredential` runs the full path fail-closed and records the credential once; authorship is the
|
|
post-quantum signature alone, so anchoring is relayable by any sender. `isValid` then re-checks a
|
|
recorded anchor LIVE, so it flips to false the instant the issuer is suspended or revoked or the
|
|
credential's status bit is set. `anchorCredentialWithDid` additionally binds and emits the subject's
|
|
`did:aere` DID string (enforcing the hash match and the `did:aere:` prefix).
|
|
|
|
The DID method is `did:aere`, consistent with AereIdentityRegistry8004's `did:aere:<chainId>:<id>`.
|
|
|
|
### 3. AereBitstringStatusList (W3C Bitstring Status List + zk non-revocation)
|
|
|
|
An on-chain implementation of the W3C Bitstring Status List v1.0 mechanism: a compact bitset where
|
|
each credential is assigned a status index, and the bit at that index encodes its status (default
|
|
0 = active). Revoking a credential flips one bit. Because one list packs many credentials, a verifier
|
|
learns only the queried bit, giving herd privacy.
|
|
|
|
- A list is created for one W3C statusPurpose: Revocation (bits are monotonic and terminal) or
|
|
Suspension (bits are reversible). Bits are packed 256 to a word and exposed via `getWord` so anyone
|
|
can recompute a commitment over the full bitstring off-chain.
|
|
- Controller-only mutation; a re-set of the same value reverts (no silent no-op).
|
|
|
|
**Zero-knowledge non-revocation ([MEASURE] circuit).** The plain read `statusOf(list, index)` reveals
|
|
the queried index. For privacy-preserving verification, a holder can instead prove in zero knowledge
|
|
that "the status bit of the credential I hold is 0" (my credential is not revoked) WITHOUT revealing
|
|
which index, bound to the list's current committed state. This file defines the verifier interface
|
|
and the exact public-input shape; the SP1 circuit is not yet built.
|
|
|
|
Public-input shape (the SP1 program's committed public values), ABI-encoded exactly as:
|
|
|
|
```
|
|
abi.encode(
|
|
uint256 chainId, // must equal block.chainid
|
|
address statusListContract, // must equal the AereBitstringStatusList address
|
|
uint256 statusListId, // the list the credential's status lives in
|
|
bytes32 statusRoot, // commitment to the bitstring the proof was made against
|
|
bytes32 credentialCommitment, // hiding commitment to the holder's credential (binds a real
|
|
// credential without revealing its status index)
|
|
uint8 purpose // must equal the list's statusPurpose
|
|
)
|
|
```
|
|
|
|
In-circuit private witness (**[MEASURE]** to be implemented): the status index `i`, an opening of
|
|
`statusRoot` at `i` proving `bitstring[i] == 0`, and an opening of `credentialCommitment` to the
|
|
credential, so the statement proven is "there is an index i, committed by credentialCommitment, whose
|
|
bit under statusRoot is 0", revealing neither `i` nor the credential.
|
|
|
|
On-chain, `verifyNonRevocation` enforces chainId / contract / listId / purpose, requires `statusRoot`
|
|
to equal the list's published root AT THE CURRENT EPOCH (so a stale proof is rejected), then delegates
|
|
the bit-is-0 statement to the SP1 verifier (reverts on an invalid proof, the canonical SP1 gateway
|
|
ABI). It is fail-closed: it reverts `NonRevocationNotConfigured` when no verifier or vkey is set, so
|
|
"unconfigured" can never be mistaken for "not revoked". **[MEASURE]** In this version the status root
|
|
is controller-attested via `publishStatusRoot`; a future version derives the root on-chain or inside
|
|
the SP1 VM from the raw words so it is trustless. The raw words are exposed regardless.
|
|
|
|
## Standards alignment
|
|
|
|
- **W3C Verifiable Credentials 2.0.** The Credential struct maps to the VC 2.0 data model: `issuer`
|
|
(the accredited issuer), `credentialSubject` (the subject DID + off-chain claims committed by
|
|
`claimsHash`), `validFrom` / `validUntil`, `type` (the `credentialType` tag), and `credentialStatus`
|
|
(a BitstringStatusListEntry: `statusListId` + `statusIndex`). The contract anchors a COMMITMENT to
|
|
the VC (digest + claims hash), not the JSON-LD document. [VERIFY] the exact JSON member names and
|
|
serialization against the finalized VC 2.0 spec before claiming wire-level conformance.
|
|
- **W3C Bitstring Status List v1.0.** Implemented directly on-chain (bitset + statusPurpose +
|
|
status index). [VERIFY] the W3C-recommended large minimum list size for herd privacy is a
|
|
deployment policy choice and is not enforced by the contract.
|
|
- **DID / did:aere.** Subjects and issuers use `did:aere`, consistent with AereIdentityRegistry8004.
|
|
The contract enforces the `did:aere:` prefix on the binding path; full DID Core syntax validation is
|
|
off-chain. [VERIFY] against a finalized did:aere method registration.
|
|
- **ERC-3643 / ONCHAINID.** ERC-3643 (T-REX) gates permissioned tokens on ONCHAINID identities that
|
|
carry signed CLAIMS from trusted claim issuers held in a Trusted Issuers Registry. AerePQ-Screen
|
|
provides the same three primitives, in the same shape: AereTrustRegistry is the trusted-issuers
|
|
registry (with scoped accreditation), AereVerifiableCredential is the claim (issuer-signed, typed,
|
|
time-bounded, subject-bound), and AereBitstringStatusList is claim revocation. The ERC-3643 claim
|
|
signature is ECDSA; AerePQ-Screen's is additionally Falcon-512. [VERIFY] a concrete ONCHAINID
|
|
claim-topic mapping (claim topic <-> `credentialType`) before asserting drop-in ERC-3643 interop.
|
|
- **eIDAS 2.0 / EUDI trusted lists.** The federated accredited-issuer model mirrors the EUDI trusted
|
|
list, where a supervisory body maintains a machine-readable list of trust service providers and
|
|
their accredited services. This is a STRUCTURAL alignment. Legal qualification under eIDAS is
|
|
external and is NOT claimed.
|
|
|
|
## The post-quantum differentiator
|
|
|
|
Every institutional identity stack in production, ERC-3643 / ONCHAINID claims, EUDI wallet
|
|
attestations, classic PKI credentials, authenticates the issuer's attestation with ECDSA or RSA,
|
|
which a cryptographically relevant quantum computer forges (harvest-now, decrypt-later applies to
|
|
long-lived compliance attestations especially). AerePQ-Screen binds an optional Falcon-512 key to each
|
|
issuer and verifies the issuer's attestation with a NIST post-quantum signature scheme in full
|
|
on-chain via the live precompile 0x0AE1. That is the property banks and regulated institutions cannot
|
|
get elsewhere, and it is the reason this passport exists.
|
|
|
|
## Files
|
|
|
|
- `aerenew/contracts/contracts/compliance/AereTrustRegistry.sol`
|
|
- `aerenew/contracts/contracts/compliance/AereVerifiableCredential.sol`
|
|
- `aerenew/contracts/contracts/compliance/AereBitstringStatusList.sol`
|
|
- `aerenew/contracts/test/aere-pq-screen.test.js` (12 passing tests)
|
|
|
|
## Test result
|
|
|
|
`npx hardhat test test/aere-pq-screen.test.js` from `aerenew/contracts`: 12 passing. Covers
|
|
accreditation lifecycle (append-only history, terminal revocation, fail-closed accreditation),
|
|
credential issue and verify with a Falcon-512 signature via the 0x0AE1 mock, revocation via the
|
|
Bitstring Status List flipping verification to false, a non-accredited (wrong-scope) issuer being
|
|
unable to issue, a tampered PQC signature failing closed, fail-closed behavior on issuer suspension
|
|
with recovery on reinstatement, expiry rejection, did:aere subject binding, and the zk non-revocation
|
|
stub's public-input shape with freshness binding (mock SP1 verifier) plus its fail-closed
|
|
unconfigured path.
|
|
|
|
## Open items ([MEASURE] / [VERIFY])
|
|
|
|
- **[MEASURE]** Implement the SP1 non-revocation circuit for the public-input shape defined above,
|
|
publish its vkey via `setNonRevocationVKey`, and wire the real SP1VerifierGateway.
|
|
- **[MEASURE]** Derive the Bitstring Status List root on-chain or in the SP1 VM (currently
|
|
controller-attested via `publishStatusRoot`).
|
|
- **[VERIFY]** Exact W3C VC 2.0 JSON serialization and member names.
|
|
- **[VERIFY]** Concrete ONCHAINID claim-topic to `credentialType` mapping for ERC-3643 interop.
|
|
- **[VERIFY]** Finalized did:aere method registration and full DID syntax validation policy.
|
|
- **[VERIFY]** W3C-recommended minimum status-list size (herd-privacy policy) at deployment.
|