#!/usr/bin/env node // genereaza-vectori.mjs: the conformance vectors, DERIVED from the producers and from evidence already recorded, never typed by hand. // // node genereaza-vectori.mjs rewrites vectori/ from: the producers run on fixed inputs (the AIP-23 kinds), the evidence // recorded on testnet 28001 beside the products (a receipt, five market timelines, a notarized // dataset commitment), and surse-proaspete.json (what needs a key, randomness or the chain) // node genereaza-vectori.mjs --verifica regenerates in memory and compares with vectori/ byte for byte: LA ZI (0) or DIFERIT (1) // node genereaza-vectori.mjs --proaspat rebuilds surse-proaspete.json: an ML-DSA-65 key made and discarded here signs a tree head, // a random envelope nobody notarized, a small dataset (random salts), and the transaction of // the recorded receipt READ from testnet 28001 (two eth_ calls; nothing is sent) // // A vector is { artifact, input, expected: { verdict, failed, levels } }. An INVALID vector names its `base` (a vector that is not // INVALID) and its `mutation`: ONE operation (set, remove, add at one JSON path) applied to the base input, so that it differs from the // base in exactly one place and must be refused for exactly the rules in `expected.failed`. Where the rule sits under a hash (an amount // under the instruction hash, an order under an index root) one place is not reachable: the mutation is then made at the PRODUCER // (`mutation.producer`), the commitments above it recomputed, and `mutation.changed` lists every path that moved. // `exercises` are the rules an implementation must be able to judge to be scored on the vector; `requires: ['rpc-28001']` marks the // vectors that need the testnet endpoint (run only with --online). import fs from 'node:fs'; import os from 'node:os'; import path from 'node:path'; import crypto from 'node:crypto'; import { fileURLToPath } from 'node:url'; import { buildProof, KINDS } from '../proof-kinds/proof-kinds.mjs'; import { buildProofOfAi } from '../proof-of-ai/proof-of-ai.mjs'; import { definePolicy, checkAction, decisionEnvelope } from '../agents/agent-policy.mjs'; import { capDeArbore } from '../verify-layer/jurnal-arbore.mjs'; import { hashIntrare } from '../verify-layer/sidecar.mjs'; import { merkleTree } from '../verify-layer/arbore-merkle.mjs'; import * as RISC from '../payments/risc.mjs'; import * as BAZA from '../verifiable-data/baza.mjs'; import { hartaPublica, LEVELS } from './reguli.mjs'; const AICI = path.dirname(fileURLToPath(import.meta.url)); const DIR = path.join(AICI, 'vectori'); const PROASPETE = path.join(AICI, 'surse-proaspete.json'); const DOV = { chitanta: new URL('../payments/dovezi/chitanta-28001-2026-10-02T1716Z.json', import.meta.url), piata: new URL('../market-settlement/dovezi/piata-28001-2026-10-02T1652Z.json', import.meta.url), date: new URL('../verifiable-data/dovezi/notarizare-28001-2026-10-02T0820Z.json', import.meta.url) }; const citeste = (u) => JSON.parse(fs.readFileSync(fileURLToPath(u), 'utf8')); const clona = (x) => JSON.parse(JSON.stringify(x)); const sha256 = (b) => '0x' + crypto.createHash('sha256').update(b).digest('hex'); const HARTA = hartaPublica(); const RPC_28001 = process.env.AERE_CONFORMANCE_RPC_28001 || 'https://testnet-rpc.aere.network'; // ---------- one operation at one path ---------- export function aplica(input, op) { const c = clona(input); let o = c; const p = op.path; for (const k of p.slice(0, -1)) { if (o == null || !(k in Object(o))) throw new Error('mutation path not in the base: ' + p.join('.')); o = o[k]; } const k = p[p.length - 1]; if (op.op === 'set') { if (!(k in Object(o))) throw new Error('set: nothing at ' + p.join('.')); o[k] = clona(op.value); } else if (op.op === 'add') { if (k in Object(o)) throw new Error('add: something already at ' + p.join('.')); o[k] = clona(op.value); } else if (op.op === 'remove') { if (!(k in Object(o))) throw new Error('remove: nothing at ' + p.join('.')); if (Array.isArray(o)) o.splice(k, 1); else delete o[k]; } else throw new Error('unknown op ' + op.op); return c; } const nivele = (failed, extra = {}) => { const n = Object.fromEntries(LEVELS.map((l) => [l, 'NOT_MEASURED'])); n.integrity = 'PASSED'; Object.assign(n, extra); for (const r of failed) { if (!HARTA[r]) throw new Error('a vector expects an unknown rule: ' + r); n[HARTA[r].level] = 'FAILED'; } return n; }; const V = []; // the vectors, in order function valid(id, artifact, title, source, input, { exercises, requires = [], verdict = 'VALID', levels = {}, base = null, mutation = null }) { V.push({ v: 1, kind: 'aere-conformance-vector', id, artifact, title, source, requires, exercises: [...exercises].sort(), base, mutation, input, expected: { verdict, failed: [], levels: nivele([], levels) } }); return input; } function invalid(id, title, bazaId, op, failed, { levels = {}, exercises = null, requires = null, producer = null } = {}) { const b = V.find((x) => x.id === bazaId); if (!b) throw new Error('no base ' + bazaId); if (b.expected.verdict === 'INVALID') throw new Error('the base of ' + id + ' is itself INVALID'); const input = producer ? producer.input : aplica(b.input, op); const mutation = producer ? { producer: producer.note, changed: producer.changed } : op; V.push({ v: 1, kind: 'aere-conformance-vector', id, artifact: b.artifact, title, source: 'derived from ' + bazaId, requires: requires || b.requires, exercises: (exercises || b.exercises).slice().sort(), base: bazaId, mutation, input, expected: { verdict: 'INVALID', failed: [...failed].sort(), levels: nivele(failed, { ...b.expected.levels, ...levels }) } }); } // ---------- the fresh sources: a key, randomness, the chain ---------- async function proaspat() { const AT = new Date().toISOString(); // (1) a signed tree head: three envelopes in a hash-chained log, the head signed with an ML-DSA-65 key that exists only in this call const INT = intrariKinds(); let prev = '0x' + '00'.repeat(32); const jurnal = ['data', 'execution', 'time'].map((k, seq) => { const proof = buildProof(k, INT[k]); const hash = hashIntrare(seq, prev, proof); const e = { seq, prev, proof, hash }; prev = hash; return e; }); const { privateKey } = crypto.generateKeyPairSync('ml-dsa-65'); const signedHead = capDeArbore(jurnal, { host: 'conformance', createdAt: AT, signKeyPem: privateKey.export({ type: 'pkcs8', format: 'pem' }) }); // (2) an envelope nobody notarized: random content const fresh = buildProof('data', { name: 'conformance-fresh', content: crypto.randomBytes(32).toString('hex'), createdAt: AT }); // (3) the transaction of the recorded receipt, read from the chain const ins = citeste(DOV.chitanta).instruction; const rpc = async (method, params) => { const r = await fetch(RPC_28001, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ jsonrpc: '2.0', id: 1, method, params }), signal: AbortSignal.timeout(20000) }); if (!r.ok) throw new Error(method + ': HTTP ' + r.status); const j = await r.json(); if (j.error || !j.result) throw new Error(method + ': ' + JSON.stringify(j.error || 'no result')); return j.result; }; const t = await rpc('eth_getTransactionByHash', [ins.txHash]); const rc = await rpc('eth_getTransactionReceipt', [ins.txHash]); const receiptTx = { chainId: 28001, readAt: AT, tx: { from: t.from, to: t.to, value: t.value, blockHash: t.blockHash }, txReceipt: { status: rc.status, blockHash: rc.blockHash } }; // (4) a small dataset: 12 records committed as version 1, 4 more as version 2 const T = fs.mkdtempSync(path.join(os.tmpdir(), 'aere-conf-set-')); let dataset; try { const TARI = ['RO', 'DE', 'FR', 'ES']; const rec = (n, de = 0) => Array.from({ length: n }, (_, j) => { const k = de + j; return { id: 'r' + k, country: TARI[k % 4], age: 20 + ((k * 7) % 40), email: 'u' + k + '@example.test', note: 'undisclosed-' + k }; }); const db = BAZA.creeaza(path.join(T, 'set'), { name: 'conformance', indexes: ['country', 'age'] }); BAZA.adauga(db, rec(12)); BAZA.angajeaza(db, { createdAt: '2026-10-03T00:00:00.000Z' }); BAZA.adauga(db, rec(4, 12)); BAZA.angajeaza(db, { createdAt: '2026-10-03T00:01:00.000Z' }); const c1 = BAZA.versiune(db, 1), c2 = BAZA.versiune(db, 2); const cerute = []; const seed = 'conformance-sample'; const k = 4; await BAZA.esantioneaza({ url: 'vector://served', commitment: c2, k, seed, ia: async (u) => { cerute.push(Number(u.split('/').pop())); return null; } }); dataset = { older: c1, newer: c2, record: BAZA.dovadaInregistrare(db, 2, 5, { fields: ['country', 'age'] }), answer: BAZA.interogheaza(db, 2, { field: 'age', from: 30, to: 45, fields: ['country'] }), consistency: BAZA.dovadaConsistenta(db, 1, 2), sample: { k, seed, served: Object.fromEntries(cerute.map((i) => [String(i), BAZA.dovadaInregistrare(db, 2, i, { fields: ['country'] })])) } }; } finally { fs.rmSync(T, { recursive: true, force: true }); } fs.writeFileSync(PROASPETE, JSON.stringify({ v: 1, kind: 'aere-conformance-fresh-sources', at: AT, signedHead, fresh, receiptTx, dataset }, null, 1) + '\n'); console.log('written ' + path.basename(PROASPETE) + ' (a signed head, a fresh envelope, the receipt transaction read from 28001, a dataset of ' + dataset.newer.size + ' records)'); } // ---------- fixed inputs of the AIP-23 kinds (the inputs of the published AIP-23 kind vectors) ---------- function intrariKinds() { const AT = '2026-09-26T00:00:00Z'; const H = (s) => sha256(Buffer.from(s, 'utf8')); return { data: { name: 'report.csv', content: 'a,b,c', createdAt: AT }, execution: { program: 'aere-node', input: 'in', output: 'out', exitCode: 0, createdAt: AT }, identity: { subjectId: 'agent-1', publicKey: 'PK', method: 'ml-dsa-65', createdAt: AT }, compliance: { subject: 'org-x', policy: 'pq-ready', result: 'pass', evidence: 'EV', createdAt: AT }, runtime: { host: 'h1', artifactContent: 'BIN', attested: H('BIN'), matches: true, createdAt: AT }, location: { subject: 'srv-eu', region: 'eu-central', evidence: 'EV', createdAt: AT }, device: { deviceId: 'dev-9', attestation: 'ATT', publicKey: 'PK', posture: 'secure-boot', createdAt: AT }, payment: { from: '0xa', to: '0xb', amount: '100', asset: 'AERE', tx: 'TX', createdAt: AT }, ownership: { owner: '0xowner', assetId: 'nft-7', asset: 'ASSET', createdAt: AT }, time: { subject: 'SUBJ', source: 'aere-anchor', at: AT, createdAt: AT }, block: { blockHash: '0x' + 'ab'.repeat(32), stateRoot: '0x' + 'cd'.repeat(32), anchorHeight: 20255488, certificateDigest: '0x' + 'ef'.repeat(32), createdAt: AT }, authorization: { grantor: 'org-x', grantee: 'agent-7', scope: 'payments:send<=100', policy: 'POLICY', expiresAt: '2026-12-31T00:00:00Z', createdAt: AT }, settlement: { chainId: 2800, txHash: '0x' + '12'.repeat(32), blockHash: '0x' + '34'.repeat(32), from: '0xa', to: '0xb', amount: '100', asset: 'AERE', instruction: 'INSTR', createdAt: AT }, provenance: { subject: 'ARTIFACT', parents: ['SRC-1', 'SRC-2'], process: 'BUILD', actor: 'build-bot', createdAt: AT } }; } /** Every AIP-23 kind, from its producer, on the fixed inputs. */ export function plicuriKinds() { const AT = '2026-09-26T00:00:00Z'; const INT = intrariKinds(); const out = []; for (const k of KINDS) { if (!INT[k]) throw new Error('proof kind ' + k + ' has no fixed input here: a new kind needs its vectors'); out.push([k, buildProof(k, INT[k])]); } out.push(['ai', buildProofOfAi({ model: { name: 'example-model', version: '1.0' }, prompt: 'summarize', output: 'summary', tools: ['search'], agentId: 'agent-7', createdAt: AT })]); const { policy, policyHash } = definePolicy({ agentId: 'agent-7', spend: { amount: '100', windowSeconds: 3600, asset: 'AERE' }, tools: ['search'], recipients: null }); const action = { kind: 'payment', to: '0xb', amount: '50', at: 1 }; out.push(['agent-decision', decisionEnvelope({ policyHash, action, decision: checkAction(policy, action, []), createdAt: AT })]); return out; } // ---------- the vectors ---------- function construieste() { if (!fs.existsSync(PROASPETE)) throw new Error('surse-proaspete.json is missing: run with --proaspat once (it reads testnet 28001)'); const P = JSON.parse(fs.readFileSync(PROASPETE, 'utf8')); const E = ['envelope.form', 'envelope.integrity']; // (A) AIP-23 envelopes: every kind VALID; its statementHash cut short (form); one statement field changed (integrity) for (const [k, env] of plicuriKinds()) { valid(`envelope/${k}.valid`, 'envelope', `the ${k} envelope from its producer`, 'producer on fixed inputs', { envelope: env }, { exercises: E }); invalid(`envelope/${k}.form`, `${k}: the statementHash is 63 hex digits`, `envelope/${k}.valid`, { op: 'set', path: ['envelope', 'statementHash'], value: env.statementHash.slice(0, -1) }, ['envelope.form']); const camp = Object.keys(env.statement).find((c) => c !== 'kind' && typeof env.statement[c] === 'string'); if (!camp) throw new Error('kind ' + k + ' has no string field to change'); invalid(`envelope/${k}.integrity`, `${k}: statement.${camp} changed after hashing`, `envelope/${k}.valid`, { op: 'set', path: ['envelope', 'statement', camp], value: env.statement[camp] + '0' }, ['envelope.integrity']); } // a signed envelope: the tree head of an audit log, ML-DSA-65 const b64 = P.signedHead.signature.signature; valid('envelope/signed-head.valid', 'envelope', 'a tree head signed with ML-DSA-65', 'producer (verify-layer tree head), key made and discarded at generation', { envelope: P.signedHead }, { exercises: [...E, 'envelope.signature'], levels: { authenticity: 'PASSED' } }); invalid('envelope/signed-head.signature', 'the signature has one character changed', 'envelope/signed-head.valid', { op: 'set', path: ['envelope', 'signature', 'signature'], value: (b64[0] === 'A' ? 'B' : 'A') + b64.slice(1) }, ['envelope.signature']); // notarization: a recorded envelope on 28001 (online), the same judged offline (the claim is not checked), a fresh one with a false claim const D = citeste(DOV.date); const F = [...E, 'envelope.finality']; const R = ['rpc-28001']; valid('envelope/notarized-28001.valid', 'envelope', 'a dataset commitment notarized on testnet 28001, read back under a verified post-quantum anchor', 'recorded (verifiable-data, 2026-10-02)', { envelope: D.envelope, chain: 28001 }, { exercises: F, requires: R, levels: { anchoring: 'PASSED', finality: 'PASSED' } }); valid('envelope/notarized-claim.partial', 'envelope', 'the same envelope judged offline: the notarization it claims is not checked, so it is not VALID', 'recorded (verifiable-data, 2026-10-02)', { envelope: D.envelope, chain: 28001 }, { exercises: E, verdict: 'PARTIAL' }); valid('envelope/fresh-28001.valid', 'envelope', 'an envelope nobody notarized, claiming nothing', 'producer, random content', { envelope: P.fresh, chain: 28001 }, { exercises: F, requires: R }); invalid('envelope/fresh-28001.finality', 'the same envelope claims a notarization the chain does not hold', 'envelope/fresh-28001.valid', { op: 'add', path: ['envelope', 'notarization'], value: { chainId: 28001 } }, ['envelope.finality']); // (B) a payment under a declared policy: the recorded payment P1, then one input changed per rule const C = citeste(DOV.chitanta); const RK = Object.keys(HARTA).filter((r) => r.startsWith('risk.')); valid('payment-risk/company-p1.valid', 'payment-risk', 'the recorded payment to a company, allowed by its policy', 'recorded (payments, 2026-10-02)', { policy: C.policy, inputs: C.inputs }, { exercises: RK }); const ref = C.policy.refusedCounterparties[0].address; const acum = C.inputs.now; const risc = (nume, titlu, op, r) => invalid('payment-risk/company-p1.' + nume, titlu, 'payment-risk/company-p1.valid', op, [r]); risc('form', 'the payer is not an address', { op: 'set', path: ['inputs', 'payer'], value: '0x1234' }, 'risk.form'); risc('form-amount', 'the amount is zero', { op: 'set', path: ['inputs', 'amount'], value: '0' }, 'risk.form'); risc('form-time', 'no time given', { op: 'remove', path: ['inputs', 'now'] }, 'risk.form'); risc('form-history', 'a history entry the engine cannot count (it is refused, not left out of the window)', { op: 'set', path: ['inputs', 'history'], value: [{ at: 'yesterday', amountUsd: '0.100000' }] }, 'risk.form'); risc('asset', 'an asset the policy does not allow', { op: 'set', path: ['inputs', 'asset'], value: 'other-token' }, 'risk.asset'); risc('counterparty', 'the payee is a refused counterparty of the policy', { op: 'set', path: ['inputs', 'payee'], value: ref }, 'risk.counterparty'); risc('rate', 'no USD rate declared, and the policy requires one', { op: 'remove', path: ['inputs', 'rate'] }, 'risk.rate'); risc('rate-number', 'the USD rate given as a JSON number instead of a decimal string (refused, not rounded)', { op: 'set', path: ['inputs', 'rate', 'usdPerUnit'], value: 0.5 }, 'risk.rate'); risc('limit', 'an amount above the per-payment limit', { op: 'set', path: ['inputs', 'amount'], value: '2400000000000000000' }, 'risk.limit'); risc('window', 'three payments already in the window (the fourth is one too many)', { op: 'set', path: ['inputs', 'history'], value: [1, 2, 3].map((s) => ({ at: acum - 10 * s, amountUsd: '0.100000' })) }, 'risk.window'); // (C) the receipt of that payment: as the issuer built it; with its notarization claim (offline: PARTIAL; online: VALID) const CK = [...Object.keys(HARTA).filter((r) => r.startsWith('receipt.')), ...E]; const claim = C.envelope.notarization; const env0 = clona(C.envelope); delete env0.notarization; const rb = 'payment-receipt/company-p1.valid'; const tx = P.receiptTx; valid(rb, 'payment-receipt', 'the recorded receipt as its issuer built it, with the policy, the inputs judged and the transaction read from the chain', 'recorded (payments, 2026-10-02); transaction read from 28001 at ' + tx.readAt, { receipt: { instruction: C.instruction, envelope: env0 }, policy: C.policy, inputs: C.inputs, tx: tx.tx, txReceipt: tx.txReceipt, chain: 28001 }, { exercises: CK }); const chit = (nume, titlu, op, r, o) => invalid('payment-receipt/company-p1.' + nume, titlu, rb, op, r, o); chit('binding', 'the purpose on the instruction changed after the envelope committed to it', { op: 'set', path: ['receipt', 'instruction', 'purpose'], value: C.instruction.purpose + ' (edited)' }, ['receipt.binding']); chit('policy', 'a looser policy shown in place of the one under the hash (so the verdict does not reproduce either)', { op: 'set', path: ['policy', 'perPaymentMaxUsd'], value: '1000.000000' }, ['receipt.policy', 'receipt.risk']); chit('risk', 'other inputs shown than the ones the issuer judged', { op: 'set', path: ['inputs', 'now'], value: C.inputs.now + 1 }, ['receipt.risk']); chit('chain', 'the transaction on chain pays someone else', { op: 'set', path: ['tx', 'to'], value: C.policy.refusedCounterparties[0].address }, ['receipt.chain']); { // the amount in USD sits under the instruction hash: the issuer writes another amount and commits to it const r = { instruction: clona(C.instruction), envelope: clona(env0) }; r.instruction.amountUsd = '0.300000'; r.envelope.statement.instructionHash = sha256(Buffer.from(RISC.canonical(r.instruction), 'utf8')); r.envelope.statementHash = sha256(Buffer.from(JSON.stringify(r.envelope.statement), 'utf8')); const b = V.find((x) => x.id === rb); chit('amount', 'the issuer wrote a USD amount that is not the amount at the declared rate, and committed to it', null, ['receipt.amount'], { producer: { note: 'instruction.amountUsd changed by the issuer; instructionHash and statementHash recomputed with the published formulas', input: { ...clona(b.input), receipt: r }, changed: [['receipt', 'instruction', 'amountUsd'], ['receipt', 'envelope', 'statement', 'instructionHash'], ['receipt', 'envelope', 'statementHash']] } }); } { // the risk verdict sits under the instruction hash: the issuer attaches a verdict made for ANOTHER payment and commits to it const b = V.find((x) => x.id === rb); const reangajeaza = (r) => { r.envelope.statement.instructionHash = sha256(Buffer.from(RISC.canonical(r.instruction), 'utf8')); r.envelope.statementHash = sha256(Buffer.from(JSON.stringify(r.envelope.statement), 'utf8')); return r; }; const cuVerdict = (inputs) => { const v = RISC.judeca(C.policy, inputs); if (v.decision !== 'ALLOW') throw new Error('the reused verdict must be an ALLOW'); const r = { instruction: clona(C.instruction), envelope: clona(env0) }; r.instruction.risk = { ...r.instruction.risk, policyHash: v.policyHash, inputsHash: v.inputsHash, verdictHash: v.verdictHash, decision: v.decision, unmeasured: v.unmeasured }; return { ...clona(b.input), receipt: reangajeaza(r), inputs }; }; const H = [['receipt', 'instruction', 'risk', 'inputsHash'], ['receipt', 'instruction', 'risk', 'verdictHash'], ['receipt', 'envelope', 'statement', 'instructionHash'], ['receipt', 'envelope', 'statementHash']]; chit('risk-other-payment', 'the issuer attached an ALLOW verdict that was made for a payment to someone else', null, ['receipt.risk'], { producer: { note: 'the risk verdict was computed for another payee; its hashes are on the instruction; instructionHash and statementHash recomputed', input: cuVerdict({ ...clona(C.inputs), payee: '0x' + '11'.repeat(20) }), changed: [['inputs', 'payee'], ...H] } }); chit('risk-other-rate', 'the issuer attached an ALLOW verdict that was made at another USD rate than the one on the receipt', null, ['receipt.risk'], { producer: { note: 'the risk verdict was computed at another rate; its hashes are on the instruction; instructionHash and statementHash recomputed', input: cuVerdict({ ...clona(C.inputs), rate: { ...C.inputs.rate, usdPerUnit: '0.25' } }), changed: [['inputs', 'rate', 'usdPerUnit'], ...H] } }); } const cuClaim = { op: 'add', path: ['receipt', 'envelope', 'notarization'], value: claim }; { const b = V.find((x) => x.id === rb); const inp = aplica(b.input, cuClaim); valid('payment-receipt/company-p1-claim.partial', 'payment-receipt', 'the notarized receipt judged offline: its notarization claim is not checked', 'recorded (payments, 2026-10-02)', inp, { exercises: CK, verdict: 'PARTIAL', base: rb, mutation: cuClaim }); valid('payment-receipt/company-p1-28001.valid', 'payment-receipt', 'the notarized receipt judged with the chain: integrity, anchoring and finality in one verdict', 'recorded (payments, 2026-10-02)', inp, { exercises: [...CK, 'envelope.finality'], requires: R, levels: { anchoring: 'PASSED', finality: 'PASSED' }, base: rb, mutation: cuClaim }); } // (D) market timelines recorded on 28001. The public task (`spec`) stays in the input only where the replay rule is exercised: // each replay recomputes the task and costs seconds. const M = citeste(DOV.piata).scenarii; const MK = Object.keys(HARTA).filter((r) => r.startsWith('market.')); const tl = (s, cuSpec) => { const d = clona(M[s].date); if (!cuSpec) delete d.spec; if (d.envelope === null) delete d.envelope; return d; }; const mv = (id, s, titlu, o = {}) => valid('market-timeline/' + id, 'market-timeline', titlu, 'recorded (market-settlement, 2026-10-02), scenario ' + s, tl(s, o.spec), { exercises: o.exercises || MK, verdict: o.verdict, requires: o.requires, levels: o.levels }); mv('s2-slashed.valid', 'S2', 'a dispute the challenger won: the provider slashed'); mv('s3-paid-after-dispute.valid', 'S3', 'a dispute the provider won'); mv('s3-paid-after-dispute-replayed.valid', 'S3', 'the same timeline with the public task: the judge recomputes it and agrees with the arbiter', { spec: true }); mv('s4-refunded-expired.valid', 'S4', 'claimed and never delivered: the escrow reclaimed after the deadline'); mv('s5-refunded-cancelled.valid', 'S5', 'posted and cancelled: the escrow returned'); mv('s1-paid-claim.partial', 'S1', 'accepted and paid; its execution envelope claims a notarization that an offline run does not check', { exercises: [...MK, ...E], verdict: 'PARTIAL' }); mv('s1-paid-28001.valid', 'S1', 'the same timeline judged with the chain: the execution envelope is under a verified post-quantum anchor', { exercises: [...MK, ...F], requires: R, levels: { anchoring: 'PASSED', finality: 'PASSED' } }); const ev = (d, n) => d.events.findIndex((e) => e.name === n); const S = (s) => V.find((x) => x.id === 'market-timeline/' + s).input; const piata = (nume, titlu, baza, op, r) => invalid('market-timeline/' + nume, titlu, 'market-timeline/' + baza, op, r); { const d = S('s2-slashed.valid'); const j = d.job; piata('s2.posting', 'the JobPosted event names another requester than the job', 's2-slashed.valid', { op: 'set', path: ['events', ev(d, 'JobPosted'), 'args', 'requester'], value: j.provider }, ['market.posting']); piata('s2.window', 'the dispute was raised after the challenge window closed', 's2-slashed.valid', { op: 'set', path: ['events', ev(d, 'JobDisputed'), 'timestamp'], value: j.submittedAt + j.challengeWindow + 5 }, ['market.window']); piata('s2.deadline-submitted', 'the result was submitted after the deadline', 's2-slashed.valid', { op: 'set', path: ['events', ev(d, 'ResultSubmitted'), 'timestamp'], value: j.deadline + 1 }, ['market.deadline']); piata('s2.arbiter', 'the dispute was resolved by an address that is not the arbiter', 's2-slashed.valid', { op: 'set', path: ['events', ev(d, 'DisputeResolved'), 'from'], value: j.requester }, ['market.arbiter']); piata('s2.payout', 'the slashed bond is paid to someone who is not the challenger', 's2-slashed.valid', { op: 'set', path: ['events', ev(d, 'JobSlashed'), 'args', 'challenger'], value: j.provider }, ['market.payout']); piata('s2.result', 'the result bytes shown do not hash to the commitment on chain', 's2-slashed.valid', { op: 'set', path: ['result'], value: d.result.slice(0, -2) + (d.result.endsWith('00') ? '01' : '00') }, ['market.result']); } { const d = S('s3-paid-after-dispute.valid'); piata('s3.payout', 'the payout names someone who is not the provider', 's3-paid-after-dispute.valid', { op: 'set', path: ['events', ev(d, 'JobPaid'), 'args', 'provider'], value: d.job.requester }, ['market.payout']); piata('s3.arbiter-no-dispute', 'the dispute withheld from the timeline: a resolution with no dispute, and an event the job state implies is missing', 's3-paid-after-dispute.valid', { op: 'remove', path: ['events', ev(d, 'JobDisputed')] }, ['market.arbiter', 'market.complete']); piata('s3.replay', 'another task shown than the one the job committed to: the recomputation contradicts the arbiter', 's3-paid-after-dispute-replayed.valid', { op: 'set', path: ['spec', 'seed'], value: '0x' + 'ab'.repeat(32) }, ['market.replay']); } { const d = S('s4-refunded-expired.valid'); piata('s4.deadline', 'the escrow was reclaimed as expired before the deadline', 's4-refunded-expired.valid', { op: 'set', path: ['events', ev(d, 'JobRefunded'), 'timestamp'], value: d.job.deadline - 1 }, ['market.deadline']); piata('s4.complete-claim', 'the claim withheld from the timeline (the job state names a provider)', 's4-refunded-expired.valid', { op: 'remove', path: ['events', ev(d, 'JobClaimed')] }, ['market.complete']); piata('s4.payout', 'the refund names someone who is not the requester', 's4-refunded-expired.valid', { op: 'set', path: ['events', ev(d, 'JobRefunded'), 'args', 'requester'], value: d.job.provider }, ['market.payout']); } { const d = S('s5-refunded-cancelled.valid'); piata('s5.form', 'an event whose time is not a whole number of seconds', 's5-refunded-cancelled.valid', { op: 'set', path: ['events', ev(d, 'JobPosted'), 'timestamp'], value: d.events[ev(d, 'JobPosted')].timestamp + 0.5 }, ['market.form']); } { const d = S('s1-paid-claim.partial'); const j = d.job; piata('s1.window', 'a third party finalized inside the challenge window', 's1-paid-claim.partial', { op: 'set', path: ['events', ev(d, 'JobPaid'), 'timestamp'], value: j.submittedAt + 1 }, ['market.window']); piata('s1.complete-submission', 'the submission withheld from the timeline (the job state has a submission time)', 's1-paid-claim.partial', { op: 'remove', path: ['events', ev(d, 'ResultSubmitted')] }, ['market.complete']); piata('s1.deadline', 'the job was claimed after its deadline', 's1-paid-claim.partial', { op: 'set', path: ['events', ev(d, 'JobClaimed'), 'timestamp'], value: j.deadline + 1 }, ['market.deadline']); piata('s1.proof-late', 'the execution envelope was notarized only after the challenge window closed', 's1-paid-claim.partial', { op: 'set', path: ['envelope', 'notarization', 'firstSeen'], value: j.submittedAt + j.challengeWindow + 1 }, ['market.proof']); piata('s1.proof-other-result', 'the execution envelope names another result (and so no longer hashes to its statementHash)', 's1-paid-claim.partial', { op: 'set', path: ['envelope', 'statement', 'outputHash'], value: '0x' + 'cc'.repeat(32) }, ['envelope.integrity', 'market.proof']); } // (E) a dataset: a record, a range answer, a consistency proof, an availability sample const DS = P.dataset; const REC = ['dataset.form', 'dataset.commitment', 'dataset.field', 'dataset.inclusion']; const src = 'producer (verifiable-data), random salts, generated ' + P.at; valid('dataset-record/r5.valid', 'dataset-record', 'one record against the commitment of version 2, two fields disclosed', src, { record: DS.record, commitment: DS.newer }, { exercises: REC }); const inr = (nume, titlu, op, r) => invalid('dataset-record/r5.' + nume, titlu, 'dataset-record/r5.valid', op, [r]); const altHex = (h) => h.slice(0, -1) + (h.endsWith('0') ? '1' : '0'); inr('form', 'the field commitments are not an object', { op: 'set', path: ['record', 'c'], value: 'x' }, 'dataset.form'); inr('commitment', 'the record names another commitment', { op: 'set', path: ['record', 'commitmentHash'], value: altHex(DS.record.commitmentHash) }, 'dataset.commitment'); inr('field', 'a disclosed value changed after commitment', { op: 'set', path: ['record', 'disclosed', 'age', 'value'], value: DS.record.disclosed.age.value + 1 }, 'dataset.field'); inr('field-no-salt', 'a disclosed field shown without its salt', { op: 'remove', path: ['record', 'disclosed', 'age', 'salt'] }, 'dataset.field'); inr('inclusion', 'one hash of the log proof changed', { op: 'set', path: ['record', 'logProof', 'path', 0], value: altHex(DS.record.logProof.path[0]) }, 'dataset.inclusion'); const ANS = [...REC, 'dataset.index', 'dataset.range', 'dataset.order', 'dataset.completeness']; if (DS.answer.rows.length < 4) throw new Error('the fresh dataset answer has under four rows; regenerate with --proaspat'); valid('dataset-answer/age-30-45.valid', 'dataset-answer', 'a range query on an indexed field: every row, and the two neighbours that prove nothing is missing', src, { answer: DS.answer, commitment: DS.newer }, { exercises: ANS }); const rasp = (nume, titlu, op, r) => invalid('dataset-answer/age-30-45.' + nume, titlu, 'dataset-answer/age-30-45.valid', op, [r]); rasp('commitment', 'an answer that names another version than the commitment it is checked against', { op: 'set', path: ['answer', 'version'], value: DS.answer.version - 1 }, 'dataset.commitment'); rasp('index-size', 'the answer states another index size than the commitment', { op: 'set', path: ['answer', 'indexSize'], value: DS.answer.indexSize + 1 }, 'dataset.commitment'); rasp('index-undisclosed', 'a row that does not disclose the queried field', { op: 'remove', path: ['answer', 'rows', 1, 'disclosed', 'age'] }, 'dataset.index'); rasp('index', 'one hash of a row\'s index proof changed', { op: 'set', path: ['answer', 'rows', 1, 'indexProof', 'path', 0], value: altHex(DS.answer.rows[1].indexProof.path[0]) }, 'dataset.index'); rasp('range', 'the answer claims a narrower range than the rows it returns', { op: 'set', path: ['answer', 'to'], value: DS.answer.rows[0].disclosed.age.value }, 'dataset.range'); rasp('completeness', 'a row dropped from the middle of the run', { op: 'remove', path: ['answer', 'rows', 1] }, 'dataset.completeness'); { // the two forgeries only the SERVER of an answer can make: a matching row withheld and shown as the neighbour that closes the run const b = V.find((x) => x.id === 'dataset-answer/age-30-45.valid'); const vecin = (r) => ({ pos: r.pos, value: r.disclosed.age.value, i: r.i, recordLeaf: BAZA.frunzaInregistrare(r.id, r.c), indexProof: r.indexProof }); const dupa = clona(b.input); const ultima = dupa.answer.rows.pop(); dupa.answer.after = vecin(ultima); invalid('dataset-answer/age-30-45.completeness-last', 'the last matching row withheld and shown as the neighbour after the run (its value is still in range)', 'dataset-answer/age-30-45.valid', null, ['dataset.completeness'], { producer: { note: 'the server dropped the last row and presented it as the neighbour after', input: dupa, changed: [['answer', 'rows', dupa.answer.rows.length], ['answer', 'after']] } }); const inainte = clona(b.input); const prima = inainte.answer.rows.shift(); inainte.answer.before = vecin(prima); invalid('dataset-answer/age-30-45.completeness-first', 'the first matching row withheld and shown as the neighbour before the run', 'dataset-answer/age-30-45.valid', null, ['dataset.completeness'], { producer: { note: 'the server dropped the first row and presented it as the neighbour before', input: inainte, changed: [['answer', 'rows'], ['answer', 'before']] } }); } { // order sits under the index root: two publishers of the same two records, one builds the index sorted, the other not const recs = [{ id: 'x', k: 'b', salt: '00'.repeat(16) }, { id: 'y', k: 'a', salt: '11'.repeat(16) }].map((r) => { const c = { k: BAZA.angajamentCamp('k', r.k, r.salt) }; return { ...r, c, leaf: BAZA.frunzaInregistrare(r.id, c) }; }); const log = merkleTree(recs.map((r) => r.leaf)); const dov = (p) => ({ index: p.index, treeSize: p.treeSize, path: p.path }); const publica = (ordine, nume) => { const idx = merkleTree(ordine.map((i) => BAZA.frunzaIndex('k', recs[i].k, i, recs[i].leaf))); const c = { v: 1, format: BAZA.FORMAT, name: nume, version: 1, size: 2, logRoot: log.root(), createdAt: '2026-10-03T00:00:00.000Z', indexes: { k: { root: idx.root(), size: 2 } }, previous: null }; const rand = (pos) => { const i = ordine[pos]; return { pos, i, id: recs[i].id, c: recs[i].c, disclosed: { k: { value: recs[i].k, salt: recs[i].salt } }, logProof: dov(log.inclusionProof(i, 2)), indexProof: dov(idx.inclusionProof(pos, 2)) }; }; return { answer: { v: 1, kind: BAZA.KIND_RASPUNS, name: nume, version: 1, commitmentHash: BAZA.hashAngajament(c), field: 'k', from: 'a', to: 'b', indexSize: 2, rows: [rand(0), rand(1)], before: null, after: null }, commitment: c }; }; valid('dataset-answer/two-records.valid', 'dataset-answer', 'two records, the index built in sorted order', 'producer formulas (verifiable-data), fixed salts', publica([1, 0], 'two-records'), { exercises: ANS }); invalid('dataset-answer/two-records.order', 'the same two records from a publisher whose index is not sorted: every proof holds, the order does not', 'dataset-answer/two-records.valid', null, ['dataset.order'], { producer: { note: 'the publisher built the index in record order instead of sorted order; the index root, the commitment hash and the rows follow from that', input: publica([0, 1], 'two-records'), changed: [['commitment', 'indexes', 'k', 'root'], ['answer', 'commitmentHash'], ['answer', 'rows']] } }); } valid('dataset-consistency/v1-v2.valid', 'dataset-consistency', 'version 1 is a prefix of version 2', src, { proof: DS.consistency, older: DS.older, newer: DS.newer }, { exercises: ['dataset.commitment', 'dataset.consistency'] }); invalid('dataset-consistency/v1-v2.commitment', 'the proof names another newer commitment', 'dataset-consistency/v1-v2.valid', { op: 'set', path: ['proof', 'to', 'commitmentHash'], value: altHex(DS.consistency.to.commitmentHash) }, ['dataset.commitment']); invalid('dataset-consistency/v1-v2.consistency', 'one hash of the consistency path changed', 'dataset-consistency/v1-v2.valid', { op: 'set', path: ['proof', 'proof', 'path', 0], value: altHex(DS.consistency.proof.path[0]) }, ['dataset.consistency']); valid('dataset-sample/four-of-sixteen.valid', 'dataset-sample', 'four positions drawn from a seed, each served and verified', src, { commitment: DS.newer, k: DS.sample.k, seed: DS.sample.seed, served: DS.sample.served }, { exercises: [...REC, 'dataset.sample'] }); invalid('dataset-sample/four-of-sixteen.sample', 'the publisher does not serve one of the sampled records', 'dataset-sample/four-of-sixteen.valid', { op: 'remove', path: ['served', Object.keys(DS.sample.served)[0]] }, ['dataset.sample']); return V; } const text = (v) => JSON.stringify(v, null, 1) + '\n'; function fisiere(vectori) { const out = new Map(); const reguli = {}; for (const v of vectori) { if (out.has(v.id + '.json')) throw new Error('two vectors with the id ' + v.id); out.set(v.id + '.json', text(v)); for (const r of v.expected.failed) (reguli[r] || (reguli[r] = [])).push(v.id); } const artifacte = {}; for (const v of vectori) artifacte[v.artifact] = (artifacte[v.artifact] || 0) + 1; const index = { v: 1, kind: 'aere-conformance-vector-index', count: vectori.length, artifacts: artifacte, offline: vectori.filter((v) => !v.requires.length).length, online: vectori.filter((v) => v.requires.length).length, rules: Object.fromEntries(Object.keys(reguli).sort().map((r) => [r, reguli[r]])), vectors: vectori.map((v) => ({ id: v.id, artifact: v.artifact, verdict: v.expected.verdict, requires: v.requires, sha256: sha256(Buffer.from(out.get(v.id + '.json'), 'utf8')) })) }; out.set('INDEX.json', text(index)); return out; } const peDisc = (d, pre = '') => (fs.existsSync(d) ? fs.readdirSync(d, { withFileTypes: true }).flatMap((e) => (e.isDirectory() ? peDisc(path.join(d, e.name), pre + e.name + '/') : [pre + e.name])) : []); if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) { const a = process.argv.slice(2); if (a.includes('--proaspat')) await proaspat(); const out = fisiere(construieste()); if (a.includes('--verifica')) { let dif = 0; for (const [f, t] of out) { const p = path.join(DIR, f); if (!fs.existsSync(p) || fs.readFileSync(p, 'utf8').replace(/\r\n/g, '\n') !== t) { dif++; console.log('DIFERIT: ' + f); } } const straine = peDisc(DIR).filter((f) => !out.has(f)); if (straine.length) { dif += straine.length; console.log('STRAINE: ' + straine.join(', ')); } console.log(dif ? `DIFERIT (${dif})` : `LA ZI (${out.size - 1} vectors + INDEX.json)`); process.exitCode = dif ? 1 : 0; } else { for (const f of peDisc(DIR)) if (!out.has(f)) fs.rmSync(path.join(DIR, f)); for (const [f, t] of out) { const p = path.join(DIR, f); fs.mkdirSync(path.dirname(p), { recursive: true }); fs.writeFileSync(p, t); } const idx = JSON.parse(out.get('INDEX.json')); console.log(`written ${idx.count} vectors (${idx.offline} offline, ${idx.online} need testnet 28001): ` + Object.entries(idx.artifacts).map(([k, n]) => k + ' ' + n).join(', ')); } }