market-settlement: the sender of a job event is read from the raw transaction (ethers does not decode the post-quantum transaction type 0x50, live on testnet 28001, and the whole timeline threw); a read-only proof re-reads the senders of the recorded run

This commit is contained in:
Aere Network 2026-10-20 13:20:52 +03:00
parent 336994f65a
commit c1721b3bf1
4 changed files with 51 additions and 3 deletions

View File

@ -1,7 +1,7 @@
# Citations in this repository that you cannot open
This file is generated by the publication stager of this repository (scripts/legaturi-declaratie.cjs in the Aere working
tree) and enforced by legaturi.cjs. It is the complete list, measured on 2026-10-19, of every path cited in this
tree) and enforced by legaturi.cjs. It is the complete list, measured on 2026-10-20, of every path cited in this
repository that does not resolve to a published file.
A citation is a promise that a claim is checkable. Where the target is not published, or names a file the reader creates

View File

@ -64,4 +64,4 @@ interface, command line and data (`definePolicy`, `verifyLedger`, `approve`, ...
## Licence
MIT, see [LICENSE](LICENSE). Files: 975 (pq-gateway 9, pq-kms 10, pq-secrets 6, pq-pki 6, crypto-inventory 73, verify-layer 56, proof-kinds 3, control-plane 27, agents 44, identity 24, proof-of-ai 3, ai-trust 6, verifiable-data 7, market-settlement 9, payments 8, conformance 646, device-identity 11, exposure-report 18, readiness 4).
MIT, see [LICENSE](LICENSE). Files: 976 (pq-gateway 9, pq-kms 10, pq-secrets 6, pq-pki 6, crypto-inventory 73, verify-layer 56, proof-kinds 3, control-plane 27, agents 44, identity 24, proof-of-ai 3, ai-trust 6, verifiable-data 7, market-settlement 10, payments 8, conformance 646, device-identity 11, exposure-report 18, readiness 4).

View File

@ -71,7 +71,14 @@ export async function cronologie({ ethers, provider, market, artifact, jobId, fr
const events = [];
for (const l of brute) {
if (!blocuri.has(l.blockHash)) blocuri.set(l.blockHash, await provider.getBlock(l.blockHash));
if (!txs.has(l.transactionHash)) txs.set(l.transactionHash, await provider.getTransaction(l.transactionHash));
// 2026-10-20: the transaction is read as the node serves it and only its sender is taken (in the checksummed form ethers gave):
// ethers' getTransaction decodes it, and it does not know the post-quantum type 0x50 (AIP-20, live on 28001), so a job event sent
// with a post-quantum transaction made the whole timeline throw
if (!txs.has(l.transactionHash)) {
const raw = await provider.send('eth_getTransactionByHash', [l.transactionHash]);
if (!raw || !raw.from) throw new Error('transaction ' + l.transactionHash + ' not found');
txs.set(l.transactionHash, { from: ethers.getAddress(raw.from) });
}
const b = blocuri.get(l.blockHash), t = txs.get(l.transactionHash);
const args = {}; l.fragment.inputs.forEach((inp, i) => { args[inp.name] = s(l.args[i]); });
events.push({ name: l.fragment.name, args, blockNumber: l.blockNumber, blockHash: l.blockHash, timestamp: b.timestamp, txHash: l.transactionHash, from: t.from, logIndex: l.index });

View File

@ -0,0 +1,41 @@
// proba-cronologie-citire.mjs (2026-10-20): piata.mjs ia acum expeditorul unui eveniment din tranzactia BRUTA (eth_getTransactionByHash,
// in forma cu majuscule de control), fiindca ethers nu decodeaza tipul post-cuantic 0x50 (AIP-20, viu pe 28001). Proba, NUMAI CITIRI: pentru
// fiecare eveniment din cea mai noua dovada dovezi/piata-28001-*.json (scrisa cu forma veche, getTransaction decodat de ethers), expeditorul
// citit acum brut e EXACT cel din dovada. Plus controlul ca forma bruta citeste si o tranzactie 0x50 reala de pe 28001, pe care ethers nu o
// decodeaza (o cauta in ultimele 400 de blocuri; daca nu gaseste, spune NEMASURAT pe acel rand, nu verde).
// (Cronologia intreaga nu se poate reciti: queryFilter de la blocul lucrarii pana la varf trece de limita de interval a RPC-ului testnetului.)
// Iesire: 0 egale, 1 diferite, 2 nu s-a putut masura. AERE_ETHERS_DIR=<dir with node_modules/ethers> node proba-cronologie-citire.mjs
import fs from 'node:fs';
import path from 'node:path';
import { createRequire } from 'node:module';
import { fileURLToPath } from 'node:url';
const AICI = path.dirname(fileURLToPath(import.meta.url));
// ethers ca la proba-piata-28001.mjs: AERE_ETHERS_DIR=<dosar cu node_modules/ethers> (implicit contracts/ din arborele de dezvoltare)
const ETHERS_DIR = process.env.AERE_ETHERS_DIR || path.join(AICI, '..', '..', 'contracts');
let ethers; try { ({ ethers } = createRequire(path.join(ETHERS_DIR, 'package.json'))('ethers')); } catch (e) { console.log('NEMASURAT: ethers nu se incarca din ' + ETHERS_DIR + ' (AERE_ETHERS_DIR)'); process.exit(2); }
const dov = fs.readdirSync(path.join(AICI, 'dovezi')).filter((f) => /^piata-28001-.*\.json$/.test(f)).sort().pop();
if (!dov) { console.log('NEMASURAT: nicio dovada piata-28001-*.json'); process.exit(2); }
const D = JSON.parse(fs.readFileSync(path.join(AICI, 'dovezi', dov), 'utf8'));
const evs = []; const aduna = (o) => { if (!o || typeof o !== 'object') return; if (o.txHash && o.from && o.name) evs.push(o); for (const v of Object.values(o)) aduna(v); }; aduna(D);
if (!evs.length) { console.log('NEMASURAT: dovada ' + dov + ' nu are evenimente cu txHash si from'); process.exit(2); }
const provider = new ethers.JsonRpcProvider(process.env.AERE_RPC_28001 || 'https://testnet-rpc.aere.network', 28001, { staticNetwork: true });
let rele = 0, vazute = new Map();
for (const e of evs) {
if (vazute.has(e.txHash)) continue;
const raw = await provider.send('eth_getTransactionByHash', [e.txHash]);
if (!raw) { console.log('NEMASURAT: tranzactia ' + e.txHash + ' nu se mai gaseste'); process.exit(2); }
const nou = ethers.getAddress(raw.from); vazute.set(e.txHash, nou);
if (nou !== e.from) { rele++; console.log(' difera ' + e.txHash.slice(0, 14) + ': ' + nou + ' / ' + e.from); }
}
console.log(`dovada ${dov}: ${vazute.size} tranzactii distincte, ${evs.length} evenimente; expeditorul brut ${rele ? 'DIFERA la ' + rele : 'egal cu cel din dovada la toate'}`);
// controlul: o tranzactie 0x50 reala de pe 28001, ethers o refuza, forma bruta o citeste
const cap = await provider.getBlockNumber(); let t50 = null;
for (let bn = cap; bn > cap - 400 && !t50; bn--) { const b = await provider.send('eth_getBlockByNumber', ['0x' + bn.toString(16), true]); t50 = (b.transactions || []).find((t) => t.type === '0x50') || null; }
if (!t50) console.log('NEMASURAT (control): nicio tranzactie 0x50 in ultimele 400 de blocuri ale lui 28001');
else {
let eth = 'citita'; try { await provider.getTransaction(t50.hash); } catch (x) { eth = 'refuzata (' + String(x.shortMessage || x.message).slice(0, 30) + ')'; }
const raw = await provider.send('eth_getTransactionByHash', [t50.hash]);
console.log('control 0x50 ' + t50.hash.slice(0, 14) + ': ethers ' + eth + '; forma bruta: expeditor ' + ethers.getAddress(raw.from));
}
console.log(rele ? 'ROSU' : 'VERDE: expeditorii cititi brut sunt cei din dovada scrisa de forma veche');
process.exitCode = rele ? 1 : 0;