// simulate.js, migration cost estimator. Given a set of accounts and a target // post-quantum scheme, estimate the gas to migrate and to authorize, using the // MEASURED PQC verify costs from the Aere benchmark report. Zero dependencies. // // All per-scheme gas is [CITED: AERE-BENCHMARK-REPORT.md Part C.1] (native // precompile marginal gas + the verify-and-record tx gasUsed receipt). The // deployed-account Falcon path is [CITED: pqc-account.json] (Solidity verifier, // ~10.5M gas). This estimator does not invent numbers; it composes the cited // ones and is explicit about which path each figure represents. import { PQC, HYBRID_MARGINAL_GAS, CLASSICAL, AERE_PQC_ACCOUNT_MEASURED_USEROP_GAS, FALCON512_SOLIDITY_VERIFIER_GAS, } from './precompiles.js'; // One-time CREATE2 deploy of an AerePQCAccount. [CITED: pqc-account.json createGasUsed] export const ACCOUNT_DEPLOY_GAS = 1493084; // The live 1 Gwei base-fee floor on chain 2800. [CITED: EIP-COMPATIBILITY-MATRIX EIP-1559 row] export const GAS_PRICE_GWEI = 1; // Per-scheme model. `verifyTxGas` is the realistic on-chain verify-and-record // receipt via the NATIVE precompile. `note` records path caveats. const SCHEME_MODEL = { falcon512: { label: 'Falcon-512 (native precompile)', verifyTxGas: PQC.falcon512.verifyAndRecordTxGas, marginal: PQC.falcon512.marginalGas }, falcon1024: { label: 'Falcon-1024 (native precompile)', verifyTxGas: PQC.falcon1024.verifyAndRecordTxGas, marginal: PQC.falcon1024.marginalGas }, mldsa44: { label: 'ML-DSA-44 (native precompile)', verifyTxGas: PQC.mldsa44.verifyAndRecordTxGas, marginal: PQC.mldsa44.marginalGas }, slhdsa128s: { label: 'SLH-DSA-128s (native precompile)', verifyTxGas: PQC.slhdsa128s.verifyAndRecordTxGas, marginal: PQC.slhdsa128s.marginalGas }, hybrid: { label: 'Hybrid ECDSA + Falcon-512 (native)', verifyTxGas: PQC.falcon512.verifyAndRecordTxGas + CLASSICAL.ecrecover.marginalGas, marginal: HYBRID_MARGINAL_GAS }, // The path an ACTUALLY-DEPLOYED AerePQCAccount takes today (Solidity verifier). falcon512_solidity: { label: 'Falcon-512 (deployed AerePQCAccount, Solidity verifier)', verifyTxGas: AERE_PQC_ACCOUNT_MEASURED_USEROP_GAS, marginal: FALCON512_SOLIDITY_VERIFIER_GAS }, }; export function schemeList() { return Object.keys(SCHEME_MODEL); } function gasToAere(gas, gweiPrice = GAS_PRICE_GWEI) { // gas * price(Gwei) * 1e-9 AERE/Gwei-gas return gas * gweiPrice * 1e-9; } /** * Estimate migration cost for a set of accounts. * @param {Array<{address?:string, scheme?:string, deployAccount?:boolean, authsPerAccount?:number}>} accounts * @param {object} opts * @param {string} opts.defaultScheme default scheme when an account omits one * @param {number} opts.defaultAuths default authorizations/account to project * @param {number} opts.gweiPrice gas price in Gwei (default 1, the live floor) */ export function simulateMigration(accounts, opts = {}) { const defaultScheme = opts.defaultScheme || 'falcon512'; const defaultAuths = opts.defaultAuths ?? 1; const gweiPrice = opts.gweiPrice ?? GAS_PRICE_GWEI; const rows = []; let totalDeployGas = 0; let totalAuthGas = 0; for (const acc of accounts) { const scheme = acc.scheme || defaultScheme; const model = SCHEME_MODEL[scheme]; if (!model) throw new Error(`unknown scheme "${scheme}". Known: ${schemeList().join(', ')}`); const deployAccount = acc.deployAccount !== false; // default: deploy a smart account const auths = acc.authsPerAccount ?? defaultAuths; const deployGas = deployAccount ? ACCOUNT_DEPLOY_GAS : 0; const authGas = model.verifyTxGas * auths; totalDeployGas += deployGas; totalAuthGas += authGas; rows.push({ address: acc.address || '(counterfactual)', scheme, schemeLabel: model.label, deployGas, authsProjected: auths, perAuthGas: model.verifyTxGas, authGas, totalGas: deployGas + authGas, }); } const totalGas = totalDeployGas + totalAuthGas; return { accounts: rows, totals: { count: accounts.length, totalDeployGas, totalAuthGas, totalGas, gweiPrice, estimatedAere: gasToAere(totalGas, gweiPrice), }, assumptions: [ `Account deploy gas = ${ACCOUNT_DEPLOY_GAS.toLocaleString()} (CREATE2 AerePQCAccount, [CITED: pqc-account.json]).`, `Per-auth gas is the native-precompile verify-and-record receipt [CITED: AERE-BENCHMARK-REPORT.md Part C.1]; the scheme "falcon512_solidity" instead models the CURRENTLY-DEPLOYED AerePQCAccount path (~10.5M gas, [CITED: pqc-account.json]).`, `Gas price = ${gweiPrice} Gwei (the live 1 Gwei base-fee floor on chain 2800).`, `SCOPE: these costs are for ACCOUNT/APPLICATION authentication. They do not make Aere consensus post-quantum.`, ], }; } /** Render a simulation result as a plain-text table for the CLI. */ export function formatSimulation(sim) { const lines = []; const pad = (s, n) => String(s).padEnd(n); const padL = (s, n) => String(s).padStart(n); lines.push(pad('ADDRESS', 26) + pad('SCHEME', 20) + padL('DEPLOY', 12) + padL('AUTHS', 7) + padL('PER-AUTH', 12) + padL('TOTAL', 14)); lines.push('-'.repeat(91)); for (const r of sim.accounts) { const a = r.address.length > 24 ? r.address.slice(0, 10) + '..' + r.address.slice(-8) : r.address; lines.push( pad(a, 26) + pad(r.scheme, 20) + padL(r.deployGas.toLocaleString(), 12) + padL(r.authsProjected, 7) + padL(r.perAuthGas.toLocaleString(), 12) + padL(r.totalGas.toLocaleString(), 14), ); } lines.push('-'.repeat(91)); const t = sim.totals; lines.push(pad(`TOTAL (${t.count} accounts)`, 46) + padL(t.totalDeployGas.toLocaleString(), 12) + padL('', 7) + padL(t.totalAuthGas.toLocaleString(), 12) + padL(t.totalGas.toLocaleString(), 14)); lines.push(''); lines.push(`Estimated cost at ${t.gweiPrice} Gwei: ${t.estimatedAere.toFixed(6)} AERE total.`); lines.push(''); lines.push('Assumptions:'); for (const a of sim.assumptions) lines.push(' - ' + a); return lines.join('\n'); }