// 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. 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');