AereAgentWallet2of2 holds the agent's tokens and accepts only the agent's signature followed by the policy service's, over the same digest. In the new cosign mode the wallet service signs only its half, after every check it already made, and the agent adds its half only after it recomputes the payment itself (payer, recipient, amount, the nonce of its own ledger entry, validity, digest, declared policy signer). verifica-plati.mjs requires the wallet's code on chain to be exactly the compiled contract with the two signers; recompileaza-contract.mjs recompiles the published artifact byte for byte with solc 0.8.23. Tests: co-signing 16/16, payment verifier 14/14, negative control 30/30, wallet 25/25. On the public testnet 28001 on 2026-09-29: 13/13 with the 2-of-2 wallet (the agent alone and the policy signer alone refused by the facilitator and by the token asked on chain) and 9/9 with the wallet key. Evidence in dovezi-28001/. Nothing here has been run on the Aere Network mainnet.
22 lines
2.1 KiB
JavaScript
22 lines
2.1 KiB
JavaScript
#!/usr/bin/env node
|
|
// inregistreaza-rpc.mjs: scoate de pe lant, O DATA, raspunsurile RPC de care are nevoie verifica-plati.mjs pentru un dosar-dovada
|
|
// (eth_chainId, chitanta fiecarei plati, Transfer-urile din portofel, si codul portofelului cand e un contract 2-din-2), ca proba verificatorului sa ruleze apoi fara retea pe date REALE.
|
|
// node inregistreaza-rpc.mjs <dovada.json> --rpc <url> --out <rpc-inregistrat.json>
|
|
import fs from 'node:fs';
|
|
import { incarcaEthers } from './wallet.mjs';
|
|
|
|
const a = process.argv.slice(2); const get = (f) => { const i = a.indexOf(f); return i >= 0 ? a[i + 1] : undefined; };
|
|
const f = a[0]; const rpc = get('--rpc'); const out = get('--out');
|
|
if (!f || !rpc || !out) { console.error('usage: node inregistreaza-rpc.mjs <evidence.json> --rpc <url> --out <file>'); process.exit(2); }
|
|
const ethers = incarcaEthers();
|
|
const d = JSON.parse(fs.readFileSync(f, 'utf8'));
|
|
const apel = async (method, params) => { const r = await fetch(rpc, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ jsonrpc: '2.0', id: 1, method, params }) }); const j = await r.json(); if (j.error) throw new Error(j.error.message); return j.result; };
|
|
const chainId = await apel('eth_chainId', []);
|
|
const receipts = {};
|
|
for (const p of d.payments) receipts[p.transaction.toLowerCase()] = await apel('eth_getTransactionReceipt', [p.transaction]);
|
|
const logs = await apel('eth_getLogs', [{ address: d.token, fromBlock: '0x' + Number(d.fromBlock).toString(16), toBlock: 'latest',
|
|
topics: [ethers.id('Transfer(address,address,uint256)'), '0x' + '0'.repeat(24) + d.wallet.toLowerCase().slice(2)] }]);
|
|
const code = d.walletContract ? await apel('eth_getCode', [d.wallet, 'latest']) : undefined;
|
|
fs.writeFileSync(out, JSON.stringify({ v: 1, recordedAt: new Date().toISOString(), rpc, chainId, receipts, transfersOut: logs, ...(code ? { code } : {}) }, null, 1) + '\n');
|
|
console.log(`recorded chain ${Number(chainId)}: ${Object.keys(receipts).length} receipts, ${logs.length} transfers out of the wallet${code ? `, the wallet code (${(code.length - 2) / 2} bytes)` : ''} -> ${out}`);
|