// precompiles.js, the single source of truth for the address bands and the // measured gas this toolkit reasons about. Every value here is sourced from a // committed repo artifact; the citations are in the comments and in README.md. // // SCOPE BOUNDARY (never moves): these are signature/hash verification // precompiles on the EVM/account path. NONE of them make Aere consensus // post-quantum. Aere mainnet (chain 2800) seals blocks with classical // secp256k1 QBFT. Migrating account authentication to a PQC scheme changes how // an account authorizes, not how the chain reaches consensus. // ── Classical, quantum-vulnerable primitives ───────────────────────────────── // Broken by a large-scale quantum computer via Shor's algorithm. export const CLASSICAL = { ecrecover: { address: 0x01n, name: 'ECDSA ecrecover (secp256k1)', quantum: 'VULNERABLE', // ecrecover is a fixed EVM protocol constant, not Aere-specific. // [VERIFY: G_ecrecover = 3000 is a fixed EVM constant.] marginalGas: 3000, }, p256: { address: 0x100n, name: 'P-256 / secp256r1 verify (RIP-7212 / RIP-7951, passkeys)', quantum: 'VULNERABLE', // Shared with Ethereum's Osaka; standards-aligned, not Aere-proprietary. // [CITED: AERE-EIP-COMPATIBILITY-MATRIX.md 0x100 row, ~3,450 gas.] marginalGas: 3450, }, }; // ── Aere's live native post-quantum precompiles (chain 2800) ───────────────── // Band 0x0AE1..0x0AE5, activated at the AerePQC fork, block 9,189,161. // [CITED: AERE-PROTOCOL-SPECIFICATION.md section 4; AERE-EIP-COMPATIBILITY-MATRIX.md; // AERE-BENCHMARK-REPORT.md Part C.1 (marginal gas + verify-and-record tx gasUsed).] export const PQC = { falcon512: { address: 0x0ae1n, name: 'Falcon-512 verify (NIST round-3)', nistLevel: 1, marginalGas: 40000, verifyAndRecordTxGas: 86336, live: true, }, falcon1024: { address: 0x0ae2n, name: 'Falcon-1024 verify (NIST round-3)', nistLevel: 5, marginalGas: 75000, verifyAndRecordTxGas: 145496, live: true, }, mldsa44: { address: 0x0ae3n, name: 'ML-DSA-44 verify (FIPS 204, Dilithium2)', nistLevel: 2, marginalGas: 55000, verifyAndRecordTxGas: 351050, live: true, }, slhdsa128s: { address: 0x0ae4n, name: 'SLH-DSA-SHA2-128s verify (FIPS 205, SPHINCS+)', nistLevel: 1, marginalGas: 350000, verifyAndRecordTxGas: 558276, live: true, }, shake256: { address: 0x0ae5n, name: 'SHAKE256 (FIPS 202 XOF)', marginalGas: 72, // 60 base + 12/word; a 32-byte input is one word -> 72 verifyAndRecordTxGas: 21470, live: true, hashOnly: true, }, }; // Testnet-only PQC precompiles, NOT on mainnet 2800. A mainnet staticcall to // these hits an empty account and returns empty. Listed so the scanner can name // them if it ever sees them, and so no one mistakes them for live mainnet. // [CITED: AERE-EIP-COMPATIBILITY-MATRIX.md 0x0AE6..0x0AE8 rows.] export const PQC_TESTNET = { mlkem768: { address: 0x0ae6n, name: 'ML-KEM-768 encapsulation (FIPS 203)', marginalGas: 60000, live: false }, falconHashToPoint: { address: 0x0ae7n, name: 'Falcon HashToPoint (SHAKE256 sampler)', live: false }, sp1StarkVerify: { address: 0x0ae8n, name: 'SP1 inner STARK verify (reference skeleton)', live: false }, }; // Hybrid cost: one Falcon-512 native verify (40,000) plus one ecrecover (3,000). // [Derived arithmetic from the two cited marginal-gas constants.] export const HYBRID_MARGINAL_GAS = PQC.falcon512.marginalGas + CLASSICAL.ecrecover.marginalGas; // 43,000 // Two Falcon-512 verify paths exist and MUST NOT be conflated: // - NATIVE precompile 0x0AE1: ~40,000 marginal / 86,336 verify-and-record tx. // - SOLIDITY AereFalcon512Verifier (0x4E8e...D8fFC): ~10.5M gas (SHAKE256 run // in-EVM). AerePQCAccount / AereHybridAuth currently delegate to this // Solidity verifier, so a *deployed* AerePQCAccount authorization is ~10.5M // gas today, NOT 86k. [CITED: contracts/deployments/pqc-account.json // handleOpsGasUsed 10,278,313; AerePQCAccount.sol GAS/EIP-7825 note.] export const FALCON512_SOLIDITY_VERIFIER_GAS = 10500000; export const AERE_PQC_ACCOUNT_MEASURED_USEROP_GAS = 10278313; // real on-chain receipt // Build a lookup of every known band address -> descriptor. export function knownAddressTable() { const t = new Map(); for (const [k, v] of Object.entries(CLASSICAL)) t.set(v.address, { key: k, band: 'classical', ...v }); for (const [k, v] of Object.entries(PQC)) t.set(v.address, { key: k, band: 'pqc-live', ...v }); for (const [k, v] of Object.entries(PQC_TESTNET)) t.set(v.address, { key: k, band: 'pqc-testnet', ...v }); return t; }