Measured 2026-08-16: a 42-byte contract that merely STORES the constant 0x0AE1 and never calls anything still scores GREEN, with the reference marked medium confidence. So the headline colour does not separate a resolved call from a bare constant, and a client who tests that in five minutes would find it before we admitted it. The scan text now says, per address, whether a CALL to each verifier resolved from the bytecode or whether only the address is present, and says plainly that a present address can also be plain data. The colour stays what the scanner computes; the sentence next to it carries what it means.
113 lines
7.6 KiB
JavaScript
113 lines
7.6 KiB
JavaScript
#!/usr/bin/env node
|
|
'use strict';
|
|
/*
|
|
* scan-gratuit.mjs - the free scan, produced as the reply a prospect actually receives.
|
|
*
|
|
* WHY THIS EXISTS. The paid report is worth 149 EUR because it is reproducible. The free scan has
|
|
* to earn the reply, not just tease it: it must tell the reader something true and useful about
|
|
* THEIR address, in language they can forward to their boss, and it must be honest about what it
|
|
* did not measure. A free scan that hides the finding behind a paywall teaches the reader that we
|
|
* hide things, which is the opposite of what we are selling.
|
|
*
|
|
* So this prints a short, plain answer, plus the exact command they can run themselves. If they
|
|
* never pay us, they still got something real, and they can check that we did not lie.
|
|
*
|
|
* node scan-gratuit.mjs 0xAddr --rpc https://rpc.aere.network
|
|
* node scan-gratuit.mjs 0xAddr --rpc URL --email # formatted as an email reply
|
|
*/
|
|
import { execFileSync } from 'node:child_process';
|
|
import path from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
import { citesteVerdict } from './lib/bytecode.js';
|
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
|
|
const argv = process.argv.slice(2);
|
|
const arg = (n, d) => { const i = argv.indexOf(n); return i >= 0 && i + 1 < argv.length ? argv[i + 1] : d; };
|
|
const ADRESA = argv.find((a) => /^0x[0-9a-fA-F]{40}$/.test(a));
|
|
const RPC = arg('--rpc', 'https://rpc.aere.network');
|
|
const EMAIL = argv.includes('--email');
|
|
|
|
if (!ADRESA) { console.error('folosire: node scan-gratuit.mjs 0xAdresa [--rpc URL] [--email]'); process.exitCode = 2; }
|
|
else {
|
|
let text = '';
|
|
try {
|
|
text = execFileSync(process.execPath, ['scan.js', ADRESA, '--rpc', RPC], { cwd: __dirname, encoding: 'utf8', timeout: 120000 }).trim();
|
|
} catch (e) { text = String((e.stdout || '') + (e.stderr || e.message)).trim(); }
|
|
|
|
// Verdictul vine din functia comuna din lib/bytecode.js. Un tipar scris aici ar fi a doua sursa
|
|
// a aceluiasi adevar, si exact asa a ajuns un contract hibrid, adica clientul care a inceput deja
|
|
// migrarea, sa primeasca "nu am putut masura adresa".
|
|
const stare = citesteVerdict(text);
|
|
const cod = (text.match(/code:\s*(\d+)\s*bytes/) || [])[1] || null;
|
|
// Eticheta de incredere e informatia care conteaza, mai mult decat culoarea verdictului: o
|
|
// referinta "call-proximate" inseamna ca apelul s-a rezolvat din bytecode, una "medium" inseamna
|
|
// ca doar constanta e prezenta si putea ajunge acolo si ca simpla data. Masurat 2026-08-16: un
|
|
// contract de 42 de octeti care doar STOCHEAZA constanta iese tot GREEN. Deci culoarea singura nu
|
|
// separa cele doua cazuri, si textul catre client trebuie sa poarte eticheta.
|
|
const refer = [...text.matchAll(/^\s*-\s*(0x[0-9a-f]+)\s+(.+?)\s*\[([a-z]+)(, call-proximate)?\]\s*$/gim)]
|
|
.map((m) => ({ nume: m[2].trim(), incredere: m[3], apel: !!m[4] }));
|
|
const verif = refer.map((r) => r.nume);
|
|
const cuApel = refer.filter((r) => r.apel).length;
|
|
const deschise = [...text.matchAll(/^\s*\*\s*(\[(?:VERIFY|MEASURE)\][^\n]*)/gim)].map((m) => m[1].trim());
|
|
|
|
// The one sentence that has to be true and has to be useful.
|
|
let verdict;
|
|
if (!stare) verdict = 'We could not measure this address from the endpoint we used. That is a result about our reach, not about your contract, and we are not going to dress it up as a finding.';
|
|
else if (!cod || cod === '0') verdict = 'This address holds no contract code, so there is nothing on chain to migrate here. Whatever authorises it is an ordinary account key, and account keys are the harder half of the problem.';
|
|
else if (verif.length) {
|
|
// The scanner finds the verifier ADDRESSES in the bytecode. Whether the contract actually
|
|
// CALLS them is a separate question the scanner often cannot settle from bytecode alone, and
|
|
// it says so in its own [VERIFY] note. Claiming "can reach" in the sales hook when the tool
|
|
// itself refused to settle it would be selling a maybe as a yes, in the first sentence a
|
|
// prospect reads. So the wording follows the measurement, and the caveat travels with it.
|
|
verdict = 'The bytecode of this contract references ' + verif.length + ' live post-quantum verifier'
|
|
+ (verif.length === 1 ? '' : 's') + ' (' + verif.slice(0, 3).join(', ') + (verif.length > 3 ? ', and more' : '') + '). '
|
|
+ (cuApel > 0
|
|
? 'For ' + cuApel + ' of them the CALL resolved from the bytecode, so the verification half of a migration is genuinely reachable in this contract.'
|
|
: 'For NONE of them could we resolve a CALL from the bytecode: the addresses are present, but a present address can also be plain data. So this is a lead, not a proven capability, and settling it needs the source or a call trace. We are telling you this because the headline verdict alone does not separate the two cases.');
|
|
}
|
|
else verdict = 'This contract reaches no post-quantum verifier. Everything it authorises today rests on ECDSA secp256k1, which is exactly the primitive the published migration timelines are about. That is the normal situation in 2026, not a criticism.';
|
|
|
|
const linii = [];
|
|
if (EMAIL) linii.push('Subject: Free quantum exposure scan for ' + ADRESA.slice(0, 10) + '...', '');
|
|
linii.push('AERE free quantum exposure scan');
|
|
linii.push('address : ' + ADRESA);
|
|
linii.push('measured: ' + new Date().toISOString().slice(0, 16).replace('T', ' ') + 'Z, chain 2800, read from ' + RPC);
|
|
linii.push('');
|
|
linii.push('WHAT WE FOUND');
|
|
linii.push(' ' + verdict);
|
|
if (stare) linii.push(' Verdict from the scanner: ' + stare + (cod ? ', ' + cod + ' bytes of code' : ''));
|
|
linii.push('');
|
|
if (deschise.length) {
|
|
linii.push('WHAT WE COULD NOT SETTLE, carried through word for word');
|
|
for (const d of deschise) linii.push(' - ' + d);
|
|
linii.push(' These are the questions the tool refuses to answer from bytecode alone. A tool that');
|
|
linii.push(' never says this is not being careful, it is being quiet.');
|
|
linii.push('');
|
|
}
|
|
linii.push('CHECK US, DO NOT TRUST US');
|
|
linii.push(' git clone https://git.aere.network/aere-network/pqc-migration-toolkit');
|
|
linii.push(' then run the same measurement against a node you operate:');
|
|
linii.push(' node scan.js ' + ADRESA + ' --rpc https://your-own-node');
|
|
linii.push(' If your number differs from ours, that difference is the interesting part and we');
|
|
linii.push(' want to hear about it.');
|
|
linii.push('');
|
|
linii.push('WHAT THE PAID REPORT ADDS, so you can decide honestly');
|
|
linii.push(' - every address in your estate, not one, with the same treatment');
|
|
linii.push(' - the answers written against the published criteria (NIST IR 8547, CNSA 2.0), in the');
|
|
linii.push(' wording a supervisor uses, as criteria and never as a certification');
|
|
linii.push(' - a digest manifest, so an edited report is detectable');
|
|
linii.push(' - the report digest anchored on chain under a post-quantum validator certificate,');
|
|
linii.push(' with a public verifier you run yourself');
|
|
linii.push(' 149 EUR, one address portfolio up to 50 for 490. Details: https://aere.network/quantum-exposure-report.html');
|
|
linii.push('');
|
|
linii.push('WHAT WE ARE NOT');
|
|
linii.push(' Not an accredited audit firm, and this is not an audit. We measure the on-chain slice:');
|
|
linii.push(' bytecode and what it can reach. Repos, TLS, dependencies and key custody are out of');
|
|
linii.push(' scope. A post-quantum verifier called from a transaction authorised with ECDSA gives');
|
|
linii.push(' no post-quantum security, and anyone telling you otherwise can be taken apart in five');
|
|
linii.push(' minutes. Our own chain has one operator and no external audit yet; we publish that.');
|
|
|
|
console.log(linii.join('\n'));
|
|
}
|