igneum/tools/reference-apps/compat/render.mjs
igneum-labs 7f0dff0722 site: fix the 2.0 audit's open items and add /docs
Pre-2.0 ledger ids pointed at 2.0 entries or dropped (M32 to D3, E19 to A7,
M4 to C1, P1/P3 to D5; E20, F7, M12 dropped); the dataset row and sentences
read the served dataset policy; engineering-log citations name
docs/bench-log.md; the node1-dn3 source notes gone; the earlier devnet named
in governance; the four words on /address, /proving and /scenes; the tx fee
sentence matches economics; provenance's SP1 sentence reads the current fact;
receipt capitals and the unlabelled timing dropped; the lock tile reads active
and total weight; TEAM-REPORTED labels on app, income, compatibility, build,
light and the dev fee row. New /docs page listing the 2.0 documents by their
master paths, wired into the build, nav, nav check, sitemap, capture and og.
docs/site/audit-2.0.md moves each fixed item into "What was rewritten".

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-08 18:14:51 +00:00

51 lines
5.5 KiB
JavaScript

// Renders tools/reference-apps/compat/results.json into docs/build/compatibility.md, the source of /compatibility (the
// builder programme's renderer turns docs/build/*.md into site pages). Run after run.mjs; both outputs are committed.
// node render.mjs [results.json]
import { readFileSync, writeFileSync, existsSync } from 'node:fs';
import path from 'node:path';
const here = path.dirname(new URL(import.meta.url).pathname);
const src = process.argv[2] || path.join(here, 'results.json');
const out = path.join(here, '..', '..', '..', 'docs', 'build', 'compatibility.md');
const res = existsSync(src) ? JSON.parse(readFileSync(src, 'utf8')) : { meta: {}, summary: { passed: 0, failed: 0, untested: 0 }, rows: [] };
const esc = s => String(s).replace(/\|/g, '\\|');
const short = h => (typeof h === 'string' && /^0x[0-9a-f]{64}$/i.test(h) ? h.slice(0, 10) + '…' + h.slice(-4) : h);
const evidence = r => Object.entries(r.evidence || {}).filter(([, v]) => ['string', 'number', 'boolean'].includes(typeof v)).map(([k, v]) => `${k} ${short(v)}`).join(', ');
const ITEMS = ['Representative contracts', 'Wallet fee estimation', 'Indexing', 'Failed transactions', 'Receipts', 'Application assumptions', 'Differences: block context', 'Differences: randomness', 'Differences: two-dimensional fees'];
const PLANNED = {
'Representative contracts': ['an ERC-20 deploys (CREATE address, code at the address)', 'ERC-20 transfer: balances, the Transfer log, eth_call', 'ERC-20 approve and transferFrom', 'a probe contract deploys', 'a counter increments and persists'],
'Wallet fee estimation': ['eth_gasPrice, eth_maxPriorityFeePerGas, eth_feeHistory shapes', 'a transfer: estimateGas against gasUsed', 'a contract call: estimateGas against gasUsed', 'the documented difference: a transfer sent with a local 21,000 limit'],
'Indexing': ['eth_getLogs by address, topic and range against the receipts', 'block, receipts and transaction lookups agree on indices'],
'Failed transactions': ['a revert: status 0, gas charged, nonce advanced, eth_call reason', 'an out-of-gas call'],
'Receipts': ['every Ethereum field, logsBloom from the logs, contractAddress on creation', 'the receipts trie root rebuilt equal to the header'],
'Application assumptions': ['block.number, timestamp, chainid, basefee, blockhash(n-1), msg.sender, tx.origin', 'CREATE2 address'],
'Differences: block context': ['block.coinbase is the including DAG block\'s miner'],
'Differences: randomness': ['block.prevrandao derives from the epoch seed, fixed per epoch'],
'Differences: two-dimensional fees': ['the receipt\'s proving dimension and the fee split'],
};
const when = res.meta.finished ? new Date(res.meta.finished).toISOString().replace('T', ' ').slice(0, 16) + ' UTC' : 'not run yet';
let md = `# Compatibility, measured
A GPU-secured network for Ethereum-compatible applications and verifiable computation. Compatibility is a product deliverable here, not a sentence: every row below is a test that ran against the devnet from the repository (\`tools/reference-apps/compat/run.mjs\`), with its evidence, and a row that could not run says so and why. Devnet, no value.
Last run: ${when}${res.meta.network ? ` on ${res.meta.network} (chain id ${res.meta.chain_id})` : ''}. ${res.summary.passed} passed, ${res.summary.failed} failed, ${res.summary.untested} untested. TEAM-REPORTED: run by the team, no outside reproduction yet. Sender ${res.meta.sender ? res.meta.sender.slice(0, 10) + '…' : 'none'}${res.meta.solc ? `, contracts compiled with solc ${res.meta.solc}` : ''}.
Three boundaries hold for everything on this page: proven execution is not finality; EVM compatibility is not Ethereum security; ZK is not privacy. The four words included, executed, proven and finalised are defined on [/receipt](/receipt).
`;
for (const item of ITEMS) {
const rows = res.rows.filter(r => r.item === item);
md += `## ${item}\n\n| Row | Verdict | What was measured | Evidence |\n|---|---|---|---|\n`;
if (rows.length) for (const r of rows) md += `| ${esc(r.name)} | **${r.verdict}** | ${esc(r.detail || '')} | ${esc(evidence(r))} |\n`;
else for (const name of PLANNED[item] || []) md += `| ${esc(name)} | **untested** | not run yet: the devnet was switched off when this page was built; the row runs on the 2.0 devnet | |\n`;
md += '\n';
}
md += `## What the differences mean for an application
- Block context: \`block.coinbase\` is the miner of the DAG block that first included the transaction, so one chain block can carry transactions with different coinbases; code that pays or trusts \`block.coinbase\` as "the block producer" sees several producers per block.
- Randomness: \`block.prevrandao\` derives from the chain's epoch seed and holds for an epoch, so it is not fresh per block and must not seed a lottery or a commitment; use an application-level randomness source.
- Two-dimensional fees: every transaction pays execution gas and proving gas; the node folds the second into the gas it quotes, so a wallet that quotes from the node (eth_estimateGas, eth_gasPrice, eth_feeHistory) is covered and a wallet with Ethereum's constants (21,000 for a transfer) is not; the receipt carries the split under \`igneum\` (pgasUsed, provingBaseFeePerGas, burnedProvingFee, burnedExecutionBaseFee, minerTip).
Source: \`tools/reference-apps/compat/run.mjs\` (the rows), \`tools/reference-apps/compat/results.json\` (the evidence), \`docs/build/compatibility.md\` (this page, rendered by \`render.mjs\`).
`;
writeFileSync(out, md);
console.log('wrote', out, res.rows.length, 'rows');