#!/usr/bin/env node // proba-judecata.mjs: the judge of the market settlement (piata.mjs) in the laboratory, without a chain, on the timelines the live run // recorded (dovezi/piata-28001-*.json, the newest): the honest timelines are VALID for their named status, and nine forged ones are // INVALID for their named reason. --control-negativ plants every PAZA marker out, one at a time, in a copy of piata.mjs and requires // the forged fixture it guards to be accepted: a check that cannot be made to fail is not a check. // Exit 0 when every row is as named; 1 otherwise; 2 when no evidence file exists (run proba-piata-28001.mjs first). // node proba-judecata.mjs [--control-negativ] env: AERE_PIATA_MODUL (the module under test; the control sets its planted copy) import fs from 'node:fs'; import path from 'node:path'; import { fileURLToPath, pathToFileURL } from 'node:url'; const AICI = path.dirname(fileURLToPath(import.meta.url)); const MODUL = process.env.AERE_PIATA_MODUL || path.join(AICI, 'piata.mjs'); const control = process.argv.includes('--control-negativ'); const dovezi = fs.existsSync(path.join(AICI, 'dovezi')) ? fs.readdirSync(path.join(AICI, 'dovezi')).filter((f) => /^piata-28001-.*\.json$/.test(f)).sort() : []; if (!dovezi.length) { console.log('NEMASURAT: no dovezi/piata-28001-*.json (run proba-piata-28001.mjs first)'); process.exit(2); } const D = JSON.parse(fs.readFileSync(path.join(AICI, 'dovezi', dovezi[dovezi.length - 1]), 'utf8')); const P = await import(pathToFileURL(MODUL).href + '?t=' + Date.now()); const clona = (x) => JSON.parse(JSON.stringify(x)); const date = (s) => { const x = D.scenarii[s]; if (!x || !x.date) throw new Error('scenario ' + s + ' has no timeline in the evidence'); return clona(x.date); }; const ev = (d, n) => d.events.find((e) => e.name === n); /** The fixtures: honest timelines (VALID, named status) and forged ones (INVALID, named reason); `paza` names the marker that guards each forgery. */ export function fixturi(P) { const F = []; for (const [s, st] of [['S1', 'Paid'], ['S2', 'Slashed'], ['S3', 'Paid'], ['S4', 'Refunded'], ['S5', 'Refunded']]) F.push({ nume: `${s} the recorded timeline is VALID with status ${st}`, asteptat: 'VALID', r: () => { const r = P.judeca(date(s)); return { verdict: r.verdict, detail: r.status + (r.replay ? ' replay providerRight=' + r.replay.providerRight : '') + '; ' + r.motive.join('; ') }; } }); F.push({ nume: 'N1 S1 finalized INSIDE the window by a third party (timestamp moved back)', asteptat: 'INVALID', paza: 'fereastra', r: () => { const d = date('S1'); ev(d, 'JobPaid').timestamp = d.job.submittedAt + 1; return v(P.judeca(d)); } }); F.push({ nume: 'N2 S2 dispute raised AFTER the window (timestamp moved forward)', asteptat: 'INVALID', paza: 'fereastra', r: () => { const d = date('S2'); ev(d, 'JobDisputed').timestamp = d.job.submittedAt + d.job.challengeWindow + 5; return v(P.judeca(d)); } }); F.push({ nume: 'N3 S2 resolved by an address that is not the arbiter', asteptat: 'INVALID', paza: 'arbitru', r: () => { const d = date('S2'); ev(d, 'DisputeResolved').from = d.job.requester; return v(P.judeca(d)); } }); F.push({ nume: 'N4 S1 claimed after the deadline (deadline moved before the claim)', asteptat: 'INVALID', paza: 'termen', r: () => { const d = date('S1'); d.job.deadline = ev(d, 'JobClaimed').timestamp - 1; ev(d, 'JobPosted').args.deadline = String(d.job.deadline); return v(P.judeca(d)); } }); F.push({ nume: 'N5 S1 paid to someone who is not the provider', asteptat: 'INVALID', paza: 'plata', r: () => { const d = date('S1'); ev(d, 'JobPaid').args.provider = d.job.requester; return v(P.judeca(d)); } }); F.push({ nume: 'N6 S1 result bytes that do not hash to the commitment', asteptat: 'INVALID', paza: 'rezultat', r: () => { const d = date('S1'); d.result = d.result.slice(0, -2) + (d.result.endsWith('00') ? '01' : '00'); return v(P.judeca(d)); } }); F.push({ nume: 'N7 S3 the arbiter sided with the provider although the replay contradicts it (spec swapped to another seed)', asteptat: 'INVALID', paza: 'replay', r: () => { const d = date('S3'); d.spec = { ...d.spec, seed: '0x' + 'ab'.repeat(32) }; d.job.specHash = P.specHash(d.spec); ev(d, 'JobPosted').args.specHash = d.job.specHash; return v(P.judeca(d)); } }); F.push({ nume: 'N8 S1 the envelope names another result (outputHash changed, statementHash kept)', asteptat: 'INVALID', paza: 'dovada', r: () => { const d = date('S1'); d.envelope.statement.outputHash = '0x' + 'cc'.repeat(32); return v(P.judeca(d)); } }); F.push({ nume: 'N9 S1 the envelope notarized only after the window closed', asteptat: 'INVALID', paza: 'dovada', r: () => { const d = date('S1'); d.envelope.notarization.firstSeen = d.job.submittedAt + d.job.challengeWindow + 1; return v(P.judeca(d)); } }); F.push({ nume: 'N10 S4 reclaimed as expired BEFORE the deadline', asteptat: 'INVALID', paza: 'termen', r: () => { const d = date('S4'); ev(d, 'JobRefunded').timestamp = d.job.deadline - 1; return v(P.judeca(d)); } }); F.push({ nume: 'R1 the settlement receipt of S1 is an AIP-23 settlement envelope naming the payout tx and the provider', asteptat: 'VALID', r: () => { const d = date('S1'); const c = P.chitanta(d); const t = ev(d, 'JobPaid'); return { verdict: c.kind === 'aere-proof-of-settlement-attestation' && c.statement.txHash === t.txHash && c.statement.to.toLowerCase() === d.job.provider.toLowerCase() && c.statement.chainId === 28001 ? 'VALID' : 'INVALID', detail: c.statementHash.slice(0, 18) + '..' }; } }); return F; } const v = (r) => ({ verdict: r.verdict, detail: r.motive.join('; ') }); if (!control) { let verzi = 0, rosii = 0, stricate = 0; for (const f of fixturi(P)) { let r; try { r = f.r(); } catch (e) { r = { verdict: 'STRICAT', detail: String(e.message).slice(0, 160) }; } const stare = r.verdict === 'STRICAT' ? 'STRICAT' : r.verdict === f.asteptat ? 'VERDE' : 'ROSU'; stare === 'VERDE' ? verzi++ : stare === 'ROSU' ? rosii++ : stricate++; console.log(` [${stare.padEnd(7)}] ${f.nume}: ${r.verdict}${r.detail ? ' (' + r.detail.slice(0, 150) + ')' : ''}`); } console.log(`\nmarket judge (evidence ${dovezi[dovezi.length - 1]}): ${verzi} VERDE, ${rosii} ROSU, ${stricate} STRICAT`); process.exitCode = rosii || stricate ? 1 : 0; } else { const SURSA = fs.readFileSync(MODUL, 'utf8'); const marcaje = ['termen', 'fereastra', 'arbitru', 'plata', 'rezultat', 'replay', 'dovada']; let bune = 0; for (const m of marcaje) { const copie = path.join(AICI, `_plantat-piata-${process.pid}-${m}.mjs`); const n = SURSA.split(`/*PAZA:${m}*/`).length - 1; const tinte = fixturi(P).filter((f) => f.paza === m); let stare, detaliu; try { if (n < 1 || !tinte.length) { stare = 'STRICAT'; detaliu = `marker ${n} times, ${tinte.length} fixtures`; } else { fs.writeFileSync(copie, SURSA.split(`/*PAZA:${m}*/`).join("|| String(1) === '1' /*PLANTAT*/")); const Q = await import(pathToFileURL(copie).href + '?t=' + Date.now()); const fx = fixturi(Q); const rez = []; for (const t of tinte) { const f = fx.find((x) => x.nume === t.nume); const r = f.r(); rez.push(`${t.nume.split(' ')[0]}:${r.verdict}`); } const toate = rez.every((x) => x.endsWith(':VALID')); stare = toate ? 'VERDE' : 'ROSU'; detaliu = (toate ? 'the forged fixture is accepted with the check planted out: ' : 'the planting did not change the verdict: ') + rez.join(' '); } } catch (e) { stare = 'STRICAT'; detaliu = String(e.message).slice(0, 160); } finally { fs.rmSync(copie, { force: true }); } if (stare === 'VERDE') bune++; console.log(` [${stare.padEnd(7)}] PAZA:${m} (${n} marker${n === 1 ? '' : 's'}) ${detaliu}`); } const ramase = fs.readdirSync(AICI).filter((f) => f.startsWith('_plantat-piata-')); console.log(`CONTROL: ${bune} of ${marcaje.length} checks proven load-bearing${ramase.length ? '; copies left: ' + ramase.join(',') : ''}`); process.exitCode = bune === marcaje.length && !ramase.length ? 0 : 1; }