aere-docs/AERE-QUANTUM-MIGRATION.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

307 lines
17 KiB
Markdown

# Aere Quantum Migration: Accounts and Network Keys
Status: user account migration is REAL and TESTED (contract + Hardhat suite,
below). Network key rotation is DESIGN ONLY and founder + audit gated. This
document is the last quantum-resistance layer at the key-management level (quantum
layer 11), and it is honest about which half is a user-callable contract today and
which half is a gated network operation.
Scope boundary, stated once and never crossed in this document: moving an account
(or a network operator) from a classical ECDSA key to a post-quantum key changes
who can authorize. It does NOT make Aere consensus post-quantum. Mainnet chain 2800
still seals blocks with classical secp256k1 QBFT, and the on-chain ZK verifiers
(BN254 Groth16) are classical. Validator-key rotation to a post-quantum scheme is
therefore coupled to the separate, gated consensus-PQC activation, not implied by
anything here.
Two flag conventions are used throughout:
- `[VERIFY]` a claim that should be confirmed against live chain state or a
deployment record before it is relied on.
- `[MEASURE]` a number or outcome that depends on a measurement or an operational
run that has not been performed here.
---
## Part A. User account migration (real, tested)
### A.1 Why migrate at all: harvest-now-decrypt-later
An Aere externally-owned account (EOA) is authorized by a secp256k1 ECDSA key. Two
facts make that a long-term liability once a cryptographically relevant quantum
computer exists:
1. ECDSA over secp256k1 is broken by Shor's algorithm. A sufficiently large
quantum computer recovers the private key from the public key.
2. An EOA reveals its public key the first time it sends a transaction (the public
key is recovered from the signature). So the exposure is not hypothetical for
any account that has ever transacted; the key material an attacker needs is
already on chain.
The threat is not "funds move today." It is "an adversary records the chain now and
breaks the keys later." That is the harvest-now-decrypt-later threat applied to
account authorization: long-dormant, high-value holdings sitting under a classical
key are exactly the accounts most worth attacking on a horizon of years. The
mitigation is to move such holdings, while the classical key is still safe, onto an
account whose spending authority is a post-quantum key.
Aere already ships the destinations for that move as live primitives. What was
missing, and what this document delivers, is a clean, no-custody path to perform
the move. That gap is quantum layer 11 in `aerenew/build-tracker/control.json`.
### A.2 The destinations: Aere's live post-quantum account primitives
The migration does not invent a new account type. It targets the ones Aere already
runs:
| Primitive | What it is | Auth | Status |
|---|---|---|---|
| `AerePQCAccount` | ERC-4337 v0.7 smart account owned solely by a NIST Falcon-512 key (897-byte pubkey) | Falcon-512 only, no ECDSA fallback | live sample `0xa42a5e7F...4326f` `[VERIFY]` |
| `AerePQCAccountFactory` | CREATE2 factory; account address is a pure function of (falconPubKey, salt) | n/a (permissionless deploy) | live `0xd5315Ea7...CE58` `[VERIFY]` |
| `AereHybridAuth` | Defense-in-depth: authorizes only if BOTH an ECDSA leg and a Falcon-512 leg verify over the same 32-byte hash | ECDSA AND Falcon-512 | repo source, no mainnet address `[VERIFY]` |
| `AereFalcon512Verifier` | Live Solidity Falcon-512 verifier the accounts delegate to | n/a | live `0x4E8e9682...D8fFC` `[VERIFY]` |
| `AerePQCKeyRegistry` | Proof-of-possession key registry | n/a | live `0x1eCa3c5A...3691` `[VERIFY]` |
Two destination shapes matter for a holder:
- PQC account (Falcon-512 only). Spending authority becomes a single lattice key.
Strongest post-quantum posture, but there is no ECDSA fallback: lose the Falcon
key and the account is gone. Register the key in `AerePQCKeyRegistry` and set PQC
social-recovery guardians BEFORE moving material value.
- Hybrid account (ECDSA + Falcon-512, via `AereHybridAuth`). Transition-era: an
attacker must break BOTH secp256k1 and Falcon-512. Good for a staged move while a
holder still wants a classical leg. `AereHybridAuth` is repo source with no
mainnet address as of 2026-07-19, so standing it up is a founder/deployer step
`[VERIFY]`.
The counterfactual address of a Falcon key's PQC account is pure CREATE2 math and
can be derived off-chain (see the migration toolkit, `aerenew/pqc-migration-toolkit`,
`predictPqcAccountAddress`, verified there against the live sample account). The
account can receive assets at that address before it is deployed, and be deployed
later via `createAccount`, which is permissionless and idempotent.
### A.3 The contract: `AereAccountMigrator`
File: `aerenew/contracts/contracts/pqc/AereAccountMigrator.sol` (solc 0.8.23,
OpenZeppelin SafeERC20 + ReentrancyGuard).
It is a pure conduit that atomically moves a caller-specified set of ERC-20
balances, and optionally native AERE, from the caller (the old EOA) to a
destination post-quantum account, in one transaction authorized by the caller's
ECDSA key. Two entrypoints:
- `migrate(destination, tokens[], amounts[], moveNative)`: move to an explicit
destination address.
- `migrateToPqcAccount(factory, falconPubKey, salt, expectedDestination, tokens[], amounts[], moveNative)`:
DERIVE the destination from a Falcon-512 key via the live
`AerePQCAccountFactory.predictAddress`, so the holder gets cryptographic
assurance they are sweeping into the post-quantum account their Falcon key
controls, and nowhere else. `expectedDestination` is an optional guard: if
non-zero it must equal the derived address, else the call reverts.
A read-only `predictPqcAccount(factory, falconPubKey, salt)` lets a frontend
confirm the destination before signing.
#### Authorization: pre-approval, or EIP-7702
The move is authorized by the caller's classical ECDSA key. The migrator does not
invent an authorization scheme; it uses ordinary ERC-20 allowances. Two supply
patterns, both documented:
1. Pre-approval (default, works today, no protocol feature). The holder sends one
`approve(migrator, amount)` per ERC-20, then calls `migrate`. Each
`safeTransferFrom` consumes the allowance and moves the tokens straight to the
destination.
2. EIP-7702 delegation (single-transaction UX). Aere supports EIP-7702 (see
`aerenew/docs/AERE-EIP-COMPATIBILITY-MATRIX.md`, row 7702 "Supported", the
EOA-delegation primitive Aere carries in place of EIP-3074). The EOA can, in one
transaction, temporarily set its account code to a batching delegate that both
approves and calls `migrate`, removing the separate approve transactions. The
migrator is agnostic to which pattern is used; under EIP-7702 the caller is
still the EOA and every invariant below is unchanged.
#### No custody, no admin (the core safety property)
- In `migrate` the caller is the `from` of every `SafeERC20.safeTransferFrom`, and
the caller-specified `destination` is the `to`. Tokens move caller to destination
in one hop. The migrator is never the recipient, so it never holds an ERC-20
balance.
- Native AERE (`msg.value`) is forwarded, in full, to that same `destination`,
inside the same call, guarded by `nonReentrant`.
- There is no owner, no admin, no upgrade, no initializer. There is no withdraw,
rescue, or sweep function, so anything accidentally sent to the migrator can
never be pulled out by anyone (stuck-but-safe, not drainable).
- There is no code path that sends value to any address other than the
caller-specified destination.
#### Fail-closed and atomic
- `destination` must be non-zero (`ZeroDestination`).
- Token and amount arrays must be equal length (`LengthMismatch`); each token
non-zero (`ZeroToken`); each amount non-zero (`ZeroAmount`).
- Native is strict: `moveNative` true requires non-zero `msg.value` (`ZeroNative`);
any `msg.value` sent while `moveNative` is false reverts (`StrayNative`), so value
can never be stranded. An empty request (no tokens, no native) reverts
(`NothingToMigrate`).
- A single failing transfer reverts the WHOLE transaction (SafeERC20 reverts on a
false/failing ERC-20), so the migration is all-or-nothing. It can never leave a
holder with a partially drained old account.
#### The `Migrated` event
`Migrated(address indexed oldAccount, address indexed newAccount, address[] tokens, uint256[] amounts, uint256 nativeAmount)`
binds the old classical account, the new post-quantum account, and the exact asset
set that moved. This is the on-chain, auditable record of a migration.
### A.4 The user flow
1. Choose a destination. Generate (or reuse) a Falcon-512 key; derive its
counterfactual `AerePQCAccount` address off-chain (toolkit
`predictPqcAccountAddress`, or the on-chain view `predictPqcAccount`). For a
hybrid transition, register an `AereHybridAuth` identity instead.
2. Prepare recovery FIRST. If the destination is Falcon-only, register the key in
`AerePQCKeyRegistry` (proof-of-possession) and set PQC social-recovery
guardians before moving material value. A Falcon-only account has no ECDSA
fallback.
3. Approve. From the old EOA, `approve(migrator, amount)` per ERC-20 (or bundle the
approvals with the migrate via EIP-7702).
4. Migrate. Call `migrateToPqcAccount(...)` (recommended, destination is bound to
your Falcon key) or `migrate(destination, ...)`. One transaction moves the
whole asset set plus optional native AERE to the destination. The `Migrated`
event is your receipt.
5. Deploy the account when convenient. `AerePQCAccountFactory.createAccount` is
permissionless and idempotent; the account can be deployed before or after the
assets arrive at its counterfactual address.
The migration toolkit (`aerenew/pqc-migration-toolkit`) is the companion that
scans an account's quantum exposure (RED/YELLOW/GREEN), derives the destination
address, and prints a step-by-step plan and a gas estimate. This contract is the
on-chain executor for step 4.
### A.5 Test result (real)
Suite: `aerenew/contracts/test/account-migrator.test.js`. Run from
`aerenew/contracts` with `npx hardhat test test/account-migrator.test.js`.
Result on 2026-07-19: 9 passing.
The destination in the strong-path tests is a REAL `AerePQCAccount` deployed
through the REAL `AerePQCAccountFactory` (the Falcon verifier is mocked because a
genuine Falcon-512 signature cannot be produced inside the hardhat process; the
CREATE2 derivation and every asset movement are fully real). Covered:
- a user migrates ERC-20 balances from an EOA to a destination in one tx (both
`migrate` and the Falcon-derived `migrateToPqcAccount`);
- native AERE forwards to the destination, with nothing stuck in the migrator;
- a zero destination reverts (`ZeroDestination`);
- a failed token transfer reverts the whole migration, and the first (would-be
successful) token is NOT moved (atomicity);
- the migrator sends only to the specified destination; an unrelated third party
receives nothing;
- no admin function exists (no owner/withdraw/rescue/sweep/transferOwnership/
initialize in the ABI), and tokens force-sent to the migrator cannot be pulled
out by anyone;
- fail-closed native handling (`StrayNative`, `ZeroNative`, `NothingToMigrate`) and
malformed asset sets (`LengthMismatch`, `ZeroToken`, `ZeroAmount`).
---
## Part B. Network key rotation (design only, founder + audit gated)
This half is DESIGN. Nothing here is a today-action, and nothing here is executed
by any contract in this repository. It is documented so the end-to-end
quantum-resistance picture is complete and honest about what remains.
There are two network-level classical keys, and they are NOT the same kind of
problem.
### B.1 Foundation operator key rotation (operational key management) `[MEASURE]`
What it is. The Foundation operator key is the ECDSA key that holds privileged
roles on operational contracts (for example NavOracle attestation, compliance
registries, the deployer/owner roles that have not yet been handed to the
Timelock). It is a normal account key, not a consensus key.
Why rotate it. Same harvest-now-decrypt-later logic as a user account: a long-lived
operator key under ECDSA is a standing liability on a multi-year horizon.
How, honestly. This is an operational key-management step, not a protocol change:
1. Stand up the post-quantum destination for the operator authority. The natural
choice is an `AerePQCAccount` (Falcon-512) or, better for an operator, a
post-quantum threshold account (the `AereThresholdAccount` family, PQC t-of-n
4337) so operator authority is not a single key. `[VERIFY]` which threshold
account is the intended operator destination.
2. Transfer each privileged role from the old ECDSA operator to the new
post-quantum account. On contracts that expose role transfer (owner /
role-grant), this is a sequence of ordinary role-transfer transactions. On
immutable core-economic contracts (Sink, sAERE, burn) there is no admin to
rotate, by design, so they need nothing.
3. Where governance is the intended long-term authority, the path is role to
Timelock, and the Post-Quantum Governance design
(`aerenew/docs/AERE-POST-QUANTUM-GOVERNANCE.md`) covers granting a PQC threshold
account the proposer/executor role on the Timelock.
Gating. This is founder-gated because it moves real privileged authority over live
contracts, and it is signed by the Foundation key, not by any contract here. It is
NOT coupled to consensus. The cost/outcome of a full rotation across the live role
set is `[MEASURE]` (it depends on the exact contracts and roles enumerated at
rotation time). No role is rotated by publishing this document.
### B.2 Validator signing key rotation (coupled to consensus-PQC) `[MEASURE]`
What it is. Each validator seals QBFT blocks with a classical secp256k1 key. This
is the consensus signing key, not an application account key.
The honest coupling. Today validator seals are classical ECDSA QBFT. Rotating a
validator's signing key to a post-quantum scheme is NOT an isolated key swap: the
consensus protocol itself has to accept and verify post-quantum seals. In other
words, a validator cannot "rotate to a Falcon seal" while the rest of the network
still expects an ECDSA seal. Validator-key rotation to PQ is therefore coupled to
the consensus-PQC activation, which is tracked as its own gated item:
- The in-place PQC activation work (hybrid ECDSA + Falcon BLOCKING seal, activated
via an anchor contract on the live chain, proven at small N in isolation) is the
mechanism that would let the seal set become post-quantum without a re-genesis.
- That flip is HIGH risk (it can halt the chain), and its gates are: N greater than
or equal to 9 validators, a soak period, an external consensus audit, and the
founder's explicit GO. See the mainnet queue in
`aerenew/build-tracker/control.json` ("Consens post-quantum LIVE", risk MARE).
So the sequence is: consensus-PQC activation FIRST (gated), and validator signing
keys rotate to their post-quantum form AS PART OF that activation, not before it
and not independently. Doing validator-key rotation "early" has no meaning while
consensus verifies classical seals.
Gating. Founder-gated AND external-audit-gated AND dependent on the consensus-PQC
item. Not a today-action. Nothing in this repository activates it. The outcome
(fork-freedom, halt/recover behavior at the target N) is `[MEASURE]` against a real
soak at N greater than or equal to 9.
### B.3 Summary of the network half
| Network key | Kind of change | Coupled to consensus? | Gate | Today-action? |
|---|---|---|---|---|
| Foundation operator key | Operational role transfer to a PQC account | No | Founder | No (founder-signed op) |
| Validator signing keys | Consensus seal scheme change | Yes | Founder + external audit + N>=9 + soak | No |
The single most important honesty point: none of this makes consensus post-quantum
by itself. The user account migration in Part A is a real, deployable-today,
no-custody contract that hardens ACCOUNT authorization. The network half in Part B
is the operator-key rotation (an operational step) plus the validator-key rotation
(inseparable from the gated consensus-PQC flip). This is the last quantum-resistance
layer, and it is largely gated, not a switch to flip tonight.
---
## Files
- `aerenew/contracts/contracts/pqc/AereAccountMigrator.sol` (contract)
- `aerenew/contracts/test/account-migrator.test.js` (Hardhat suite, 9 passing)
- `aerenew/pqc-migration-toolkit/` (scanner + derivation + cost simulator)
- `aerenew/contracts/contracts/pqc/AerePQCAccount.sol`,
`AerePQCAccountFactory.sol`, `AereHybridAuth.sol` (destinations)
- `aerenew/docs/AERE-POST-QUANTUM-GOVERNANCE.md` (Timelock role grant to a PQC
threshold account, the governance path for operator authority)
- `aerenew/docs/AERE-EIP-COMPATIBILITY-MATRIX.md` (EIP-7702 support)