Zero dependencies, no account, no API. Every command takes --rpc, so it runs against a node you operate and never needs ours. That is the point: an exposure measurement you cannot re-run is an opinion with a logo on it. Ships with two self-checks meant to be run by you, not just by us. The second, proba-vocabular.mjs, exists because of a real defect found on 2026-08-16: the scanner emits RED / YELLOW / GREEN, two downstream files each wrote their own copy of that list, and both wrote AMBER, so a hybrid contract, exactly a client who has already started migrating, was reported as unmeasurable. Both sides were self-consistent, so nothing we had could see it. The vocabulary now has one exported source, and the test walks the whole path with a negative control that makes it able to fail. The same scanner returns RED about our own contracts. See VERIFY-US.md.
111 lines
4.7 KiB
JavaScript
111 lines
4.7 KiB
JavaScript
// 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;
|
|
}
|