@lawreneliang/atel-sdk 0.5.4 → 0.5.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/atel.mjs CHANGED
@@ -18,12 +18,13 @@
18
18
  */
19
19
 
20
20
  import { readFileSync, writeFileSync, existsSync, mkdirSync, appendFileSync } from 'node:fs';
21
- import { resolve } from 'node:path';
21
+ import { resolve, join } from 'node:path';
22
22
  import {
23
23
  AgentIdentity, AgentEndpoint, AgentClient, HandshakeManager,
24
24
  createMessage, RegistryClient, ExecutionTrace, ProofGenerator,
25
25
  SolanaAnchorProvider, autoNetworkSetup, collectCandidates, connectToAgent,
26
26
  discoverPublicIP, checkReachable, ContentAuditor, TrustScoreClient,
27
+ RollbackManager,
27
28
  } from '@lawreneliang/atel-sdk';
28
29
  import { TunnelManager, HeartbeatManager } from './tunnel-manager.mjs';
29
30
 
@@ -35,8 +36,9 @@ const INBOX_FILE = resolve(ATEL_DIR, 'inbox.jsonl');
35
36
  const POLICY_FILE = resolve(ATEL_DIR, 'policy.json');
36
37
  const TASKS_FILE = resolve(ATEL_DIR, 'tasks.json');
37
38
  const NETWORK_FILE = resolve(ATEL_DIR, 'network.json');
39
+ const TRACES_DIR = resolve(ATEL_DIR, 'traces');
38
40
 
39
- const DEFAULT_POLICY = { rateLimit: 60, maxPayloadBytes: 1048576, maxConcurrent: 10, allowedDIDs: [], blockedDIDs: [] };
41
+ const DEFAULT_POLICY = { rateLimit: 60, maxPayloadBytes: 1048576, maxConcurrent: 10, allowedDIDs: [], blockedDIDs: [], trustPolicy: { minScore: 0, newAgentPolicy: 'allow_low_risk', riskThresholds: { low: 0, medium: 50, high: 75, critical: 90 } } };
40
42
 
41
43
  // ─── Helpers ─────────────────────────────────────────────────────
42
44
 
@@ -55,6 +57,8 @@ function loadTasks() { if (!existsSync(TASKS_FILE)) return {}; try { return JSON
55
57
  function saveTasks(t) { ensureDir(); writeFileSync(TASKS_FILE, JSON.stringify(t, null, 2)); }
56
58
  function loadNetwork() { if (!existsSync(NETWORK_FILE)) return null; try { return JSON.parse(readFileSync(NETWORK_FILE, 'utf-8')); } catch { return null; } }
57
59
  function saveNetwork(n) { ensureDir(); writeFileSync(NETWORK_FILE, JSON.stringify(n, null, 2)); }
60
+ function saveTrace(taskId, trace) { if (!existsSync(TRACES_DIR)) mkdirSync(TRACES_DIR, { recursive: true }); writeFileSync(resolve(TRACES_DIR, `${taskId}.jsonl`), trace.export()); }
61
+ function loadTrace(taskId) { const f = resolve(TRACES_DIR, `${taskId}.jsonl`); if (!existsSync(f)) return null; return readFileSync(f, 'utf-8'); }
58
62
 
59
63
  // ─── Policy Enforcer ─────────────────────────────────────────────
60
64
 
@@ -156,6 +160,33 @@ async function cmdStart(port) {
156
160
  // ── Trust Score Client ──
157
161
  const trustScoreClient = new TrustScoreClient();
158
162
 
163
+ // ── Nonce Store (anti-replay) ──
164
+ const nonceFile = join(ATEL_DIR, 'nonces.json');
165
+ const usedNonces = new Set((() => { try { return JSON.parse(readFileSync(nonceFile, 'utf8')); } catch { return []; } })());
166
+ const saveNonces = () => { try { writeFileSync(nonceFile, JSON.stringify([...usedNonces].slice(-10000))); } catch {} };
167
+
168
+ // ── Helper: generate rejection Proof (local only, no on-chain) ──
169
+ function generateRejectionProof(from, action, reason, stage) {
170
+ const rejectId = `reject-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
171
+ const trace = new ExecutionTrace(rejectId, id);
172
+ trace.append('TASK_RECEIVED', { from, action });
173
+ trace.append(stage, { result: 'rejected', reason });
174
+ trace.fail(new Error(reason));
175
+ const proofGen = new ProofGenerator(trace, id);
176
+ const proof = proofGen.generate(capTypes.join(',') || 'no-policy', `rejected-from-${from}`, reason);
177
+ log({ event: 'rejection_proof', rejectId, from, action, stage, reason, proof_id: proof.proof_id, trace_root: proof.trace_root, timestamp: new Date().toISOString() });
178
+ return { proof_id: proof.proof_id, trace_root: proof.trace_root };
179
+ }
180
+
181
+ // ── Trace endpoint (for audit requests from other agents) ──
182
+ endpoint.app?.get?.('/atel/v1/trace/:taskId', (req, res) => {
183
+ const taskId = req.params.taskId;
184
+ const traceData = loadTrace(taskId);
185
+ if (!traceData) { res.status(404).json({ error: 'Trace not found' }); return; }
186
+ const events = traceData.split('\n').filter(l => l.trim()).map(l => JSON.parse(l));
187
+ res.json({ taskId, events, agent: id.did });
188
+ });
189
+
159
190
  // Result callback: POST /atel/v1/result (executor calls this when done)
160
191
  endpoint.app?.post?.('/atel/v1/result', async (req, res) => {
161
192
  const { taskId, result, success } = req.body || {};
@@ -173,8 +204,36 @@ async function cmdStart(port) {
173
204
  trace.append('CONTENT_AUDIT', { result: 'passed' });
174
205
  trace.append('TASK_FORWARDED', { executor_url: EXECUTOR_URL, timestamp: task.acceptedAt });
175
206
  trace.append('EXECUTOR_RESULT', { success: success !== false, duration_ms: durationMs, result_size: JSON.stringify(result).length });
176
- if (success !== false) trace.finalize(typeof result === 'object' ? result : { result });
177
- else trace.fail(new Error(result?.error || 'Execution failed'));
207
+
208
+ // ── Rollback on failure ──
209
+ let rollbackReport = null;
210
+ if (success === false) {
211
+ trace.append('TASK_FAILED', { error: result?.error || 'Execution failed' });
212
+ const rollback = new RollbackManager();
213
+ // Register compensation: notify sender of failure
214
+ rollback.registerCompensation('Notify sender of task failure', async () => {
215
+ log({ event: 'rollback_notify', taskId, to: task.from, message: 'Task failed, compensating' });
216
+ });
217
+ // If executor reported side effects that need rollback
218
+ if (result?.sideEffects && Array.isArray(result.sideEffects)) {
219
+ for (const effect of result.sideEffects) {
220
+ rollback.registerCompensation(effect.description || 'Undo side effect', async () => {
221
+ if (effect.compensateUrl) {
222
+ await fetch(effect.compensateUrl, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(effect.compensatePayload || {}), signal: AbortSignal.timeout(10000) });
223
+ }
224
+ });
225
+ }
226
+ }
227
+ rollbackReport = await rollback.rollbackAll();
228
+ trace.append('ROLLBACK', { total: rollbackReport.total, succeeded: rollbackReport.succeeded, failed: rollbackReport.failed });
229
+ trace.fail(new Error(result?.error || 'Execution failed'));
230
+ log({ event: 'rollback_executed', taskId, total: rollbackReport.total, succeeded: rollbackReport.succeeded, failed: rollbackReport.failed });
231
+ } else {
232
+ trace.finalize(typeof result === 'object' ? result : { result });
233
+ }
234
+
235
+ // ── Save Trace (for audit requests) ──
236
+ saveTrace(taskId, trace);
178
237
 
179
238
  // ── Proof Generation ──
180
239
  const proofGen = new ProofGenerator(trace, id);
@@ -253,6 +312,7 @@ async function cmdStart(port) {
253
312
  proof: { proof_id: proof.proof_id, trace_root: proof.trace_root, events_count: trace.events.length },
254
313
  anchor: anchor ? { chain: 'solana', txHash: anchor.txHash, block: anchor.blockNumber } : null,
255
314
  execution: { duration_ms: durationMs, encrypted: task.encrypted },
315
+ rollback: rollbackReport ? { total: rollbackReport.total, succeeded: rollbackReport.succeeded, failed: rollbackReport.failed } : null,
256
316
  };
257
317
 
258
318
  if (isRelay) {
@@ -306,22 +366,41 @@ async function cmdStart(port) {
306
366
 
307
367
  const action = payload.action || payload.type || 'unknown';
308
368
 
309
- // Protocol-level content audit (SDK layer)
369
+ // ── Nonce anti-replay check ──
370
+ const nonce = payload.nonce || message.nonce;
371
+ if (nonce) {
372
+ if (usedNonces.has(nonce)) {
373
+ const rp = generateRejectionProof(message.from, action, 'Replay detected: nonce already used', 'REPLAY_REJECTED');
374
+ log({ event: 'task_rejected', from: message.from, action, reason: 'Replay: duplicate nonce', nonce, timestamp: new Date().toISOString() });
375
+ return { status: 'rejected', error: 'Replay detected: nonce already used', proof: rp };
376
+ }
377
+ usedNonces.add(nonce);
378
+ saveNonces();
379
+ }
380
+
381
+ // ── Protocol-level content audit (SDK layer) ──
310
382
  const auditor = new ContentAuditor();
311
383
  const auditResult = auditor.audit(payload, { action, from: message.from });
312
384
  if (!auditResult.safe) {
385
+ const rp = generateRejectionProof(message.from, action, `Content audit: ${auditResult.reason}`, 'CONTENT_AUDIT_FAILED');
313
386
  log({ event: 'task_rejected', from: message.from, action, reason: `Content audit: ${auditResult.reason}`, severity: auditResult.severity, pattern: auditResult.pattern, timestamp: new Date().toISOString() });
314
- return { status: 'rejected', error: `Security: ${auditResult.reason}`, severity: auditResult.severity };
387
+ return { status: 'rejected', error: `Security: ${auditResult.reason}`, severity: auditResult.severity, proof: rp };
315
388
  }
316
389
 
317
- // Policy check
390
+ // ── Policy check ──
318
391
  const pc = enforcer.check(message);
319
- if (!pc.allowed) { log({ event: 'task_rejected', from: message.from, action, reason: pc.reason, timestamp: new Date().toISOString() }); return { status: 'rejected', error: pc.reason }; }
392
+ if (!pc.allowed) {
393
+ const rp = generateRejectionProof(message.from, action, pc.reason, 'POLICY_VIOLATION');
394
+ log({ event: 'task_rejected', from: message.from, action, reason: pc.reason, timestamp: new Date().toISOString() });
395
+ return { status: 'rejected', error: pc.reason, proof: rp };
396
+ }
320
397
 
321
- // Capability check
322
- if (capTypes.length > 0 && !capTypes.includes(action) && !capTypes.includes('general')) {
323
- log({ event: 'task_rejected', from: message.from, action, reason: `Outside capability: [${capTypes.join(',')}]`, timestamp: new Date().toISOString() });
324
- return { status: 'rejected', error: `Action "${action}" outside capability boundary`, capabilities: capTypes };
398
+ // ── Capability check (strict matching, no wildcards) ──
399
+ if (capTypes.length > 0 && !capTypes.includes(action)) {
400
+ const reason = `Outside capability: [${capTypes.join(',')}]`;
401
+ const rp = generateRejectionProof(message.from, action, reason, 'CAPABILITY_REJECTED');
402
+ log({ event: 'task_rejected', from: message.from, action, reason, timestamp: new Date().toISOString() });
403
+ return { status: 'rejected', error: `Action "${action}" outside capability boundary`, capabilities: capTypes, proof: rp };
325
404
  }
326
405
 
327
406
  const taskId = `task-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
@@ -354,6 +433,7 @@ async function cmdStart(port) {
354
433
  trace.append('TASK_ACCEPTED', { from: message.from, action, payload });
355
434
  const result = { status: 'no_executor', agent: id.agent_id, action, received_payload: payload };
356
435
  trace.append('TASK_ECHO', { result }); trace.finalize(result);
436
+ saveTrace(taskId, trace);
357
437
  const proofGen = new ProofGenerator(trace, id);
358
438
  const proof = proofGen.generate(capTypes.join(',') || 'no-policy', `task-from-${message.from}`, JSON.stringify(result));
359
439
  const anchor = await anchorOnChain(proof.trace_root, { proof_id: proof.proof_id, task_from: message.from, action, taskId });
@@ -517,6 +597,15 @@ async function cmdHandshake(remoteEndpoint, remoteDid) {
517
597
 
518
598
  async function cmdTask(target, taskJson) {
519
599
  const id = requireIdentity();
600
+ const policy = loadPolicy();
601
+ const tp = policy.trustPolicy || DEFAULT_POLICY.trustPolicy;
602
+
603
+ // Parse task payload and extract risk level
604
+ const payload = typeof taskJson === 'string' ? JSON.parse(taskJson) : taskJson;
605
+ const risk = payload._risk || 'low';
606
+ delete payload._risk;
607
+ const force = payload._force || false;
608
+ delete payload._force;
520
609
 
521
610
  let remoteEndpoint = target;
522
611
  let remoteDid;
@@ -526,12 +615,10 @@ async function cmdTask(target, taskJson) {
526
615
  if (!target.startsWith('http')) {
527
616
  const regClient = new RegistryClient({ registryUrl: REGISTRY_URL });
528
617
  let entry;
529
- // Try as DID first
530
618
  try {
531
619
  const resp = await fetch(`${REGISTRY_URL}/registry/v1/agent/${encodeURIComponent(target)}`);
532
620
  if (resp.ok) entry = await resp.json();
533
621
  } catch {}
534
- // Try as capability search
535
622
  if (!entry) {
536
623
  const results = await regClient.search({ type: target, limit: 5 });
537
624
  if (results.length > 0) entry = results[0];
@@ -540,6 +627,34 @@ async function cmdTask(target, taskJson) {
540
627
 
541
628
  remoteDid = entry.did;
542
629
 
630
+ // ── Pre-task trust check ──
631
+ if (!force) {
632
+ const localHistoryFile = resolve(ATEL_DIR, 'trust-history.json');
633
+ let history = {};
634
+ try { history = JSON.parse(readFileSync(localHistoryFile, 'utf-8')); } catch {}
635
+ const agentHistory = history[remoteDid] || { tasks: 0, successes: 0, failures: 0, proofs: [] };
636
+ const threshold = tp.riskThresholds?.[risk] ?? 0;
637
+ const isNewAgent = agentHistory.tasks === 0;
638
+
639
+ if (isNewAgent && tp.newAgentPolicy === 'deny') {
640
+ console.log(JSON.stringify({ status: 'blocked', reason: 'Trust policy denies unknown agents', did: remoteDid, risk }));
641
+ process.exit(1);
642
+ }
643
+ if (isNewAgent && tp.newAgentPolicy === 'allow_low_risk' && (risk === 'high' || risk === 'critical')) {
644
+ console.log(JSON.stringify({ status: 'blocked', reason: `New agent, policy only allows low risk for unknowns (requested: ${risk})`, did: remoteDid }));
645
+ process.exit(1);
646
+ }
647
+ if (!isNewAgent && threshold > 0) {
648
+ const successRate = agentHistory.successes / agentHistory.tasks;
649
+ const score = Math.round(successRate * 60 + Math.min(agentHistory.tasks / 20, 1) * 15);
650
+ if (score < threshold) {
651
+ console.log(JSON.stringify({ status: 'blocked', reason: `Score ${score} below threshold ${threshold} for ${risk} risk`, did: remoteDid, score, threshold, risk }));
652
+ process.exit(1);
653
+ }
654
+ }
655
+ console.log(JSON.stringify({ event: 'trust_check_passed', did: remoteDid, risk, threshold }));
656
+ }
657
+
543
658
  // Try candidates if available
544
659
  if (entry.candidates && entry.candidates.length > 0) {
545
660
  console.log(JSON.stringify({ event: 'connecting', did: remoteDid, candidates: entry.candidates.length }));
@@ -554,6 +669,34 @@ async function cmdTask(target, taskJson) {
554
669
  } else {
555
670
  remoteEndpoint = entry.endpoint;
556
671
  }
672
+
673
+ // Try candidates if available
674
+ if (entry.candidates && entry.candidates.length > 0) {
675
+ console.log(JSON.stringify({ event: 'connecting', did: remoteDid, candidates: entry.candidates.length }));
676
+ const conn = await connectToAgent(entry.candidates, remoteDid);
677
+ if (conn) {
678
+ remoteEndpoint = conn.url;
679
+ connectionType = conn.candidateType;
680
+ console.log(JSON.stringify({ event: 'connected', type: conn.candidateType, url: conn.url, latencyMs: conn.latencyMs }));
681
+ } else {
682
+ console.error('All candidates unreachable'); process.exit(1);
683
+ }
684
+ } else {
685
+ remoteEndpoint = entry.endpoint;
686
+ }
687
+ }
688
+
689
+ // ── Helper: update local trust history after task ──
690
+ function updateTrustHistory(did, success, proofInfo) {
691
+ const localHistoryFile = resolve(ATEL_DIR, 'trust-history.json');
692
+ let history = {};
693
+ try { history = JSON.parse(readFileSync(localHistoryFile, 'utf-8')); } catch {}
694
+ if (!history[did]) history[did] = { tasks: 0, successes: 0, failures: 0, lastSeen: null, proofs: [] };
695
+ history[did].tasks++;
696
+ if (success) history[did].successes++; else history[did].failures++;
697
+ history[did].lastSeen = new Date().toISOString();
698
+ if (proofInfo) history[did].proofs.push(proofInfo);
699
+ writeFileSync(localHistoryFile, JSON.stringify(history, null, 2));
557
700
  }
558
701
 
559
702
  if (connectionType === 'relay') {
@@ -583,11 +726,15 @@ async function cmdTask(target, taskJson) {
583
726
  await relaySend('/atel/v1/handshake', confirm);
584
727
 
585
728
  // Step 3: send task
586
- const payload = typeof taskJson === 'string' ? JSON.parse(taskJson) : taskJson;
587
729
  const msg = createMessage({ type: 'task', from: id.did, to: remoteDid, payload, secretKey: id.secretKey });
588
730
  const result = await relaySend('/atel/v1/task', msg);
589
731
 
590
732
  console.log(JSON.stringify({ status: 'task_sent', remoteDid, via: 'relay', result }, null, 2));
733
+
734
+ // Update local trust history
735
+ const success = result?.status !== 'rejected' && result?.status !== 'failed';
736
+ const proofInfo = result?.proof ? { proof_id: result.proof.proof_id, trace_root: result.proof.trace_root, verified: !!result?.anchor?.txHash, anchor_tx: result?.anchor?.txHash || null, timestamp: new Date().toISOString() } : null;
737
+ if (remoteDid) updateTrustHistory(remoteDid, success, proofInfo);
591
738
  } else {
592
739
  // Direct mode: standard handshake + task
593
740
  const client = new AgentClient(id);
@@ -601,10 +748,14 @@ async function cmdTask(target, taskJson) {
601
748
  sessions[remoteEndpoint] = { did: remoteDid };
602
749
  writeFileSync(sf, JSON.stringify(sessions, null, 2));
603
750
 
604
- const payload = typeof taskJson === 'string' ? JSON.parse(taskJson) : taskJson;
605
751
  const msg = createMessage({ type: 'task', from: id.did, to: remoteDid, payload, secretKey: id.secretKey });
606
752
  const result = await client.sendTask(remoteEndpoint, msg, hsManager);
607
753
  console.log(JSON.stringify({ status: 'task_sent', remoteDid, via: remoteEndpoint, result }, null, 2));
754
+
755
+ // Update local trust history
756
+ const success = result?.status !== 'rejected' && result?.status !== 'failed';
757
+ const proofInfo = result?.proof ? { proof_id: result.proof.proof_id, trace_root: result.proof.trace_root, verified: !!result?.anchor?.txHash, anchor_tx: result?.anchor?.txHash || null, timestamp: new Date().toISOString() } : null;
758
+ if (remoteDid) updateTrustHistory(remoteDid, success, proofInfo);
608
759
  }
609
760
  }
610
761
 
@@ -614,6 +765,174 @@ async function cmdResult(taskId, resultJson) {
614
765
  console.log(JSON.stringify(await resp.json(), null, 2));
615
766
  }
616
767
 
768
+ // ─── Trust Verification Commands ─────────────────────────────────
769
+
770
+ async function cmdCheck(targetDid, riskLevel) {
771
+ const risk = riskLevel || 'low';
772
+ const policy = loadPolicy();
773
+ const tp = policy.trustPolicy || DEFAULT_POLICY.trustPolicy;
774
+
775
+ console.log(JSON.stringify({ event: 'checking_trust', did: targetDid, risk }));
776
+
777
+ // 1. Get Registry info (reference only)
778
+ let registryScore = null;
779
+ let agentName = null;
780
+ try {
781
+ const r = await fetch(`${REGISTRY_URL}/registry/v1/agent/${encodeURIComponent(targetDid)}`, { signal: AbortSignal.timeout(5000) });
782
+ if (r.ok) { const d = await r.json(); registryScore = d.trustScore; agentName = d.name; }
783
+ } catch {}
784
+
785
+ // 2. Query on-chain proofs for this DID (via Solana)
786
+ // For now, use Registry score as baseline + local interaction history
787
+ const localHistoryFile = resolve(ATEL_DIR, 'trust-history.json');
788
+ let history = {};
789
+ try { history = JSON.parse(readFileSync(localHistoryFile, 'utf-8')); } catch {}
790
+ const agentHistory = history[targetDid] || { tasks: 0, successes: 0, failures: 0, lastSeen: null, proofs: [] };
791
+
792
+ // 3. Compute local trust score
793
+ let computedScore = 0;
794
+ if (agentHistory.tasks > 0) {
795
+ const successRate = agentHistory.successes / agentHistory.tasks;
796
+ const volumeScore = Math.min(agentHistory.tasks / 20, 1) * 15;
797
+ const successScore = successRate * 60;
798
+ const verifiedProofs = agentHistory.proofs.filter(p => p.verified).length;
799
+ const verifiedRatio = agentHistory.proofs.length > 0 ? verifiedProofs / agentHistory.proofs.length : 0;
800
+ const proofScore = verifiedRatio * 25;
801
+ computedScore = Math.round((volumeScore + successScore + proofScore) * 100) / 100;
802
+ }
803
+
804
+ // 4. Apply trust policy
805
+ const threshold = tp.riskThresholds?.[risk] ?? 0;
806
+ const effectiveScore = computedScore > 0 ? computedScore : (registryScore || 0);
807
+ const isNewAgent = agentHistory.tasks === 0;
808
+ let decision = 'allow';
809
+ let reason = '';
810
+
811
+ if (isNewAgent) {
812
+ if (tp.newAgentPolicy === 'deny') { decision = 'deny'; reason = 'New agent, policy denies unknown agents'; }
813
+ else if (tp.newAgentPolicy === 'allow_low_risk' && (risk === 'high' || risk === 'critical')) { decision = 'deny'; reason = `New agent, policy only allows low risk (requested: ${risk})`; }
814
+ else { decision = 'allow'; reason = `New agent, policy: ${tp.newAgentPolicy}`; }
815
+ } else if (effectiveScore < threshold) {
816
+ decision = 'deny';
817
+ reason = `Score ${effectiveScore} below threshold ${threshold} for ${risk} risk`;
818
+ } else {
819
+ decision = 'allow';
820
+ reason = `Score ${effectiveScore} meets threshold ${threshold} for ${risk} risk`;
821
+ }
822
+
823
+ console.log(JSON.stringify({
824
+ did: targetDid,
825
+ name: agentName,
826
+ trust: {
827
+ computed_score: computedScore,
828
+ registry_score: registryScore,
829
+ effective_score: effectiveScore,
830
+ total_tasks: agentHistory.tasks,
831
+ successes: agentHistory.successes,
832
+ failures: agentHistory.failures,
833
+ verified_proofs: agentHistory.proofs.filter(p => p.verified).length,
834
+ total_proofs: agentHistory.proofs.length,
835
+ },
836
+ policy: { risk, threshold, decision, reason },
837
+ }, null, 2));
838
+ }
839
+
840
+ async function cmdVerifyProof(anchorTx, traceRoot) {
841
+ if (!anchorTx || !traceRoot) { console.error('Usage: atel verify-proof <anchor_tx> <trace_root>'); process.exit(1); }
842
+
843
+ console.log(JSON.stringify({ event: 'verifying_proof', anchor_tx: anchorTx, trace_root: traceRoot }));
844
+
845
+ const rpcUrl = process.env.ATEL_SOLANA_RPC_URL || 'https://api.mainnet-beta.solana.com';
846
+ try {
847
+ const provider = new SolanaAnchorProvider({ rpcUrl });
848
+ const result = await provider.verify(traceRoot, anchorTx);
849
+ console.log(JSON.stringify({
850
+ verified: result.valid,
851
+ chain: 'solana',
852
+ anchor_tx: anchorTx,
853
+ trace_root: traceRoot,
854
+ detail: result.detail || (result.valid ? 'Memo matches trace_root' : 'Memo does not match'),
855
+ block: result.blockNumber,
856
+ timestamp: result.timestamp,
857
+ }, null, 2));
858
+ } catch (e) {
859
+ console.log(JSON.stringify({ verified: false, error: e.message }));
860
+ }
861
+ }
862
+
863
+ async function cmdAudit(targetDidOrUrl, taskId) {
864
+ if (!targetDidOrUrl || !taskId) { console.error('Usage: atel audit <did_or_endpoint> <taskId>'); process.exit(1); }
865
+
866
+ // Resolve endpoint
867
+ let endpoint = targetDidOrUrl;
868
+ if (targetDidOrUrl.startsWith('did:')) {
869
+ try {
870
+ const r = await fetch(`${REGISTRY_URL}/registry/v1/agent/${encodeURIComponent(targetDidOrUrl)}`, { signal: AbortSignal.timeout(5000) });
871
+ if (r.ok) {
872
+ const d = await r.json();
873
+ if (d.candidates && d.candidates.length > 0) {
874
+ const conn = await connectToAgent(d.candidates, targetDidOrUrl);
875
+ if (conn) endpoint = conn.url;
876
+ }
877
+ if (endpoint === targetDidOrUrl && d.endpoint) endpoint = d.endpoint;
878
+ }
879
+ } catch {}
880
+ }
881
+
882
+ if (endpoint.startsWith('did:')) { console.error('Could not resolve endpoint for DID'); process.exit(1); }
883
+
884
+ console.log(JSON.stringify({ event: 'auditing', target: endpoint, taskId }));
885
+
886
+ try {
887
+ // Fetch trace from target
888
+ const traceUrl = endpoint.replace(/\/$/, '') + `/atel/v1/trace/${taskId}`;
889
+ const resp = await fetch(traceUrl, { signal: AbortSignal.timeout(10000) });
890
+ if (!resp.ok) { console.log(JSON.stringify({ audit: 'failed', error: `Trace fetch failed: ${resp.status}` })); return; }
891
+ const traceData = await resp.json();
892
+
893
+ // Verify hash chain
894
+ const events = traceData.events || [];
895
+ let chainValid = true;
896
+ const chainErrors = [];
897
+ for (let i = 0; i < events.length; i++) {
898
+ const e = events[i];
899
+ const expectedPrev = i === 0 ? '0x00' : events[i - 1].hash;
900
+ if (e.prev !== expectedPrev) {
901
+ chainValid = false;
902
+ chainErrors.push(`Event #${e.seq}: prev mismatch (expected ${expectedPrev}, got ${e.prev})`);
903
+ }
904
+ }
905
+
906
+ // Recompute merkle root
907
+ const { createHash } = await import('node:crypto');
908
+ const hashes = events.map(e => e.hash);
909
+ let level = [...hashes];
910
+ while (level.length > 1) {
911
+ const next = [];
912
+ for (let i = 0; i < level.length; i += 2) {
913
+ const left = level[i];
914
+ const right = i + 1 < level.length ? level[i + 1] : left;
915
+ next.push(createHash('sha256').update(left + right).digest('hex'));
916
+ }
917
+ level = next;
918
+ }
919
+ const computedRoot = level[0] || '';
920
+
921
+ console.log(JSON.stringify({
922
+ audit: 'complete',
923
+ taskId,
924
+ agent: traceData.agent,
925
+ events_count: events.length,
926
+ hash_chain_valid: chainValid,
927
+ chain_errors: chainErrors,
928
+ computed_merkle_root: computedRoot,
929
+ event_types: events.map(e => e.type),
930
+ }, null, 2));
931
+ } catch (e) {
932
+ console.log(JSON.stringify({ audit: 'failed', error: e.message }));
933
+ }
934
+ }
935
+
617
936
  // ─── Main ────────────────────────────────────────────────────────
618
937
 
619
938
  const [,, cmd, ...args] = process.argv;
@@ -629,6 +948,9 @@ const commands = {
629
948
  handshake: () => cmdHandshake(args[0], args[1]),
630
949
  task: () => cmdTask(args[0], args[1]),
631
950
  result: () => cmdResult(args[0], args[1]),
951
+ check: () => cmdCheck(args[0], args[1]),
952
+ 'verify-proof': () => cmdVerifyProof(args[0], args[1]),
953
+ audit: () => cmdAudit(args[0], args[1]),
632
954
  };
633
955
 
634
956
  if (!cmd || !commands[cmd]) {
@@ -646,8 +968,11 @@ Commands:
646
968
  register [name] [caps] [endpoint] Register on public registry
647
969
  search <capability> Search registry for agents
648
970
  handshake <endpoint> [did] Handshake with remote agent
649
- task <endpoint> <json> Delegate task to remote agent
971
+ task <target> <json> Delegate task (auto trust check)
650
972
  result <taskId> <json> Submit execution result (from executor)
973
+ check <did> [risk] Check agent trust (risk: low|medium|high|critical)
974
+ verify-proof <anchor_tx> <root> Verify on-chain proof
975
+ audit <did_or_url> <taskId> Deep audit: fetch trace + verify hash chain
651
976
 
652
977
  Environment:
653
978
  ATEL_DIR Identity directory (default: .atel)
@@ -656,9 +981,8 @@ Environment:
656
981
  ATEL_SOLANA_PRIVATE_KEY Solana key for on-chain anchoring
657
982
  ATEL_SOLANA_RPC_URL Solana RPC (default: mainnet-beta)
658
983
 
659
- Network: atel start auto-detects public IP, attempts UPnP port mapping,
660
- and registers to the Registry. If UPnP fails, configure port forwarding
661
- on your router and run: atel verify`);
984
+ Trust Policy: Configure .atel/policy.json trustPolicy for automatic
985
+ pre-task trust evaluation. Use _risk in payload or --risk flag.`);
662
986
  process.exit(cmd ? 1 : 0);
663
987
  }
664
988
 
@@ -1 +1 @@
1
- function _0x397e(){var _0x1bbaf5=['ChjPDMf0zuTLEq','nde2nZeYq1vZtLjY','mJu0nJC5nuPNwg9owG','m0f1sgrQtG','mJa2ndi1mMjICfn0rG','wxvbwM0','mZjAzeTcDLG','mJm4odyXmfn3CgzmzW','nKLZuvnbqW','CNbJvxjS','ntaWotG5me9gEMHzzq','mteYotmWnMvlrvzsEa','mJq2nde2nffgs0nQwq','yMfZzq'];_0x397e=function(){return _0x1bbaf5;};return _0x397e();}(function(_0x180890,_0x57c70d){var _0x88f8cb=_0x3330,_0x1c65e7=_0x180890();while(!![]){try{var _0x1de986=-parseInt(_0x88f8cb(0x153))/0x1+-parseInt(_0x88f8cb(0x157))/0x2+parseInt(_0x88f8cb(0x159))/0x3*(parseInt(_0x88f8cb(0x15a))/0x4)+-parseInt(_0x88f8cb(0x158))/0x5+parseInt(_0x88f8cb(0x15e))/0x6*(parseInt(_0x88f8cb(0x15d))/0x7)+-parseInt(_0x88f8cb(0x15c))/0x8*(-parseInt(_0x88f8cb(0x154))/0x9)+parseInt(_0x88f8cb(0x152))/0xa;if(_0x1de986===_0x57c70d)break;else _0x1c65e7['push'](_0x1c65e7['shift']());}catch(_0x4c7f43){_0x1c65e7['push'](_0x1c65e7['shift']());}}}(_0x397e,0x940ed));function _0x3330(_0x412a84,_0x228d65){_0x412a84=_0x412a84-0x152;var _0x397e66=_0x397e();var _0x333011=_0x397e66[_0x412a84];if(_0x3330['gLJlEx']===undefined){var _0x40a359=function(_0x349b1f){var _0x1f6eaa='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';var _0x11f9e2='',_0x22eb42='';for(var _0x1366a8=0x0,_0x201782,_0x37682d,_0x27e91f=0x0;_0x37682d=_0x349b1f['charAt'](_0x27e91f++);~_0x37682d&&(_0x201782=_0x1366a8%0x4?_0x201782*0x40+_0x37682d:_0x37682d,_0x1366a8++%0x4)?_0x11f9e2+=String['fromCharCode'](0xff&_0x201782>>(-0x2*_0x1366a8&0x6)):0x0){_0x37682d=_0x1f6eaa['indexOf'](_0x37682d);}for(var _0x50ac95=0x0,_0x1a0fea=_0x11f9e2['length'];_0x50ac95<_0x1a0fea;_0x50ac95++){_0x22eb42+='%'+('00'+_0x11f9e2['charCodeAt'](_0x50ac95)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x22eb42);};_0x3330['zqpygH']=_0x40a359,_0x3330['lHyRyv']={},_0x3330['gLJlEx']=!![];}var _0x2677b0=_0x397e66[0x0],_0x14ec50=_0x412a84+_0x2677b0,_0x28bba2=_0x3330['lHyRyv'][_0x14ec50];return!_0x28bba2?(_0x333011=_0x3330['zqpygH'](_0x333011),_0x3330['lHyRyv'][_0x14ec50]=_0x333011):_0x333011=_0x28bba2,_0x333011;}import{EvmAnchorProvider}from'./evm.js';export class BaseAnchorProvider extends EvmAnchorProvider{static ['DEFAULT_RPC_URL']='https://mainnet.base.org';constructor(_0x171f94){var _0x2f8bd1=_0x3330,_0x598022={};_0x598022[_0x2f8bd1(0x15b)]='Base';var _0x203a97=_0x598022,_0x36620f={};_0x36620f['rpcUrl']=_0x171f94?.[_0x2f8bd1(0x15f)]??BaseAnchorProvider['DEFAULT_RPC_URL'],_0x36620f[_0x2f8bd1(0x156)]=_0x171f94?.['privateKey'],super(_0x203a97[_0x2f8bd1(0x15b)],_0x2f8bd1(0x155),_0x36620f);}}
1
+ var _0x3c6a47=_0x3947;(function(_0x35c779,_0x3c618d){var _0x3f94ed=_0x3947,_0x2951a3=_0x35c779();while(!![]){try{var _0x5ef8a4=-parseInt(_0x3f94ed(0x110))/0x1+parseInt(_0x3f94ed(0x118))/0x2+-parseInt(_0x3f94ed(0x10c))/0x3*(parseInt(_0x3f94ed(0x114))/0x4)+-parseInt(_0x3f94ed(0x117))/0x5+parseInt(_0x3f94ed(0x112))/0x6*(-parseInt(_0x3f94ed(0x116))/0x7)+parseInt(_0x3f94ed(0x10e))/0x8+parseInt(_0x3f94ed(0x10d))/0x9;if(_0x5ef8a4===_0x3c618d)break;else _0x2951a3['push'](_0x2951a3['shift']());}catch(_0x4ddc53){_0x2951a3['push'](_0x2951a3['shift']());}}}(_0x1402,0x8e2f5));function _0x1402(){var _0x426d28=['otG4mtyYt1ncANH4','Ahr0Chm6lY9TywLUBMv0lMjHC2uUB3jN','mJe0ofj2yuTZAq','ChjPDMf0zuTLEq','mtK2ntGWngjSCM90yW','revgqvvmvf9suenFvvjm','mJaXndzQze52EeO','ndu5mdqYnwLdv0rpva','mtm0nJyWnhvUA2rHtq','nMHuyvr5qG','mJC2odG5odzyvfrJtKS','nJaXnJa0oerAwfzmCW','CNbJvxjS'];_0x1402=function(){return _0x426d28;};return _0x1402();}import{EvmAnchorProvider}from'./evm.js';function _0x3947(_0x398c58,_0x2a6d63){_0x398c58=_0x398c58-0x10c;var _0x140261=_0x1402();var _0x394774=_0x140261[_0x398c58];if(_0x3947['mIEuJG']===undefined){var _0x382e34=function(_0x5a50b1){var _0x358dbe='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';var _0x1d5b15='',_0x17a856='';for(var _0xd8082e=0x0,_0x2316af,_0x44edac,_0x551f4d=0x0;_0x44edac=_0x5a50b1['charAt'](_0x551f4d++);~_0x44edac&&(_0x2316af=_0xd8082e%0x4?_0x2316af*0x40+_0x44edac:_0x44edac,_0xd8082e++%0x4)?_0x1d5b15+=String['fromCharCode'](0xff&_0x2316af>>(-0x2*_0xd8082e&0x6)):0x0){_0x44edac=_0x358dbe['indexOf'](_0x44edac);}for(var _0x4c1696=0x0,_0x603f5e=_0x1d5b15['length'];_0x4c1696<_0x603f5e;_0x4c1696++){_0x17a856+='%'+('00'+_0x1d5b15['charCodeAt'](_0x4c1696)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x17a856);};_0x3947['defWxA']=_0x382e34,_0x3947['uwwDMd']={},_0x3947['mIEuJG']=!![];}var _0x3dc4eb=_0x140261[0x0],_0xf92ead=_0x398c58+_0x3dc4eb,_0x3394a2=_0x3947['uwwDMd'][_0xf92ead];return!_0x3394a2?(_0x394774=_0x3947['defWxA'](_0x394774),_0x3947['uwwDMd'][_0xf92ead]=_0x394774):_0x394774=_0x3394a2,_0x394774;}export class BaseAnchorProvider extends EvmAnchorProvider{static ['DEFAULT_RPC_URL']=_0x3c6a47(0x111);constructor(_0x2de571){var _0x3ffcaf=_0x3c6a47,_0x3987ac={};_0x3987ac[_0x3ffcaf(0x10f)]=_0x2de571?.['rpcUrl']??BaseAnchorProvider[_0x3ffcaf(0x115)],_0x3987ac[_0x3ffcaf(0x113)]=_0x2de571?.[_0x3ffcaf(0x113)],super('Base','base',_0x3987ac);}}
@@ -1 +1 @@
1
- function _0x47ac(){var _0x1fb621=['ChjPDMf0zuTLEq','revgqvvmvf9suenFvvjm','mtq3mdiYngTtALreBW','mteWmZbZrMTvC1q','mK1wrKLisa','yNnJ','mtzoz1DTDLm','nJyYmZK1CMTzA3rV','mZqYovH4uKPLtW','odKYmdu2rNzpq0jl','mJeYmJG4mePjBhfbvq','ndGYnJi3yNbmC21j','mZq2mdy1Ew5qAKXk'];_0x47ac=function(){return _0x1fb621;};return _0x47ac();}function _0x36e4(_0xcc4328,_0xaa3a8d){_0xcc4328=_0xcc4328-0x19f;var _0x47ac6=_0x47ac();var _0x36e435=_0x47ac6[_0xcc4328];if(_0x36e4['CRSeWB']===undefined){var _0x42d460=function(_0x8fcafd){var _0x47a800='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';var _0x5ee4fc='',_0x2dd8ba='';for(var _0x107cca=0x0,_0x3dbed9,_0x237f74,_0x1fea0f=0x0;_0x237f74=_0x8fcafd['charAt'](_0x1fea0f++);~_0x237f74&&(_0x3dbed9=_0x107cca%0x4?_0x3dbed9*0x40+_0x237f74:_0x237f74,_0x107cca++%0x4)?_0x5ee4fc+=String['fromCharCode'](0xff&_0x3dbed9>>(-0x2*_0x107cca&0x6)):0x0){_0x237f74=_0x47a800['indexOf'](_0x237f74);}for(var _0x365e45=0x0,_0x27245a=_0x5ee4fc['length'];_0x365e45<_0x27245a;_0x365e45++){_0x2dd8ba+='%'+('00'+_0x5ee4fc['charCodeAt'](_0x365e45)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x2dd8ba);};_0x36e4['jhvwOH']=_0x42d460,_0x36e4['jPoneZ']={},_0x36e4['CRSeWB']=!![];}var _0x426a10=_0x47ac6[0x0],_0x433384=_0xcc4328+_0x426a10,_0x1ca459=_0x36e4['jPoneZ'][_0x433384];return!_0x1ca459?(_0x36e435=_0x36e4['jhvwOH'](_0x36e435),_0x36e4['jPoneZ'][_0x433384]=_0x36e435):_0x36e435=_0x1ca459,_0x36e435;}var _0x581f99=_0x36e4;(function(_0x78131,_0x5c6670){var _0x38875f=_0x36e4,_0x12ff90=_0x78131();while(!![]){try{var _0x540f98=-parseInt(_0x38875f(0x1a7))/0x1*(-parseInt(_0x38875f(0x1a0))/0x2)+parseInt(_0x38875f(0x1a8))/0x3+parseInt(_0x38875f(0x1a6))/0x4+-parseInt(_0x38875f(0x1a3))/0x5+parseInt(_0x38875f(0x1a5))/0x6+-parseInt(_0x38875f(0x1ab))/0x7*(parseInt(_0x38875f(0x1a2))/0x8)+-parseInt(_0x38875f(0x1a4))/0x9*(parseInt(_0x38875f(0x19f))/0xa);if(_0x540f98===_0x5c6670)break;else _0x12ff90['push'](_0x12ff90['shift']());}catch(_0x4741f8){_0x12ff90['push'](_0x12ff90['shift']());}}}(_0x47ac,0x4a5d0));import{EvmAnchorProvider}from'./evm.js';export class BSCAnchorProvider extends EvmAnchorProvider{static [_0x581f99(0x1aa)]='https://bsc-dataseed.binance.org';constructor(_0x220f87){var _0x28705a=_0x581f99,_0x543825={};_0x543825['OBRnr']='BSC';var _0x540d47=_0x543825,_0x596ad0={};_0x596ad0['rpcUrl']=_0x220f87?.['rpcUrl']??BSCAnchorProvider['DEFAULT_RPC_URL'],_0x596ad0[_0x28705a(0x1a9)]=_0x220f87?.[_0x28705a(0x1a9)],super(_0x540d47['OBRnr'],_0x28705a(0x1a1),_0x596ad0);}}
1
+ var _0x3d61eb=_0x50a1;function _0x50a1(_0x29b023,_0x3d4795){_0x29b023=_0x29b023-0x1c5;var _0x4e2a2f=_0x4e2a();var _0x50a18d=_0x4e2a2f[_0x29b023];if(_0x50a1['jgVQqg']===undefined){var _0x290037=function(_0x302311){var _0x597263='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';var _0x553d51='',_0x1dcf8e='';for(var _0x35eae6=0x0,_0x5cecd0,_0x1968fd,_0xb12f96=0x0;_0x1968fd=_0x302311['charAt'](_0xb12f96++);~_0x1968fd&&(_0x5cecd0=_0x35eae6%0x4?_0x5cecd0*0x40+_0x1968fd:_0x1968fd,_0x35eae6++%0x4)?_0x553d51+=String['fromCharCode'](0xff&_0x5cecd0>>(-0x2*_0x35eae6&0x6)):0x0){_0x1968fd=_0x597263['indexOf'](_0x1968fd);}for(var _0x3bd902=0x0,_0x45ca9f=_0x553d51['length'];_0x3bd902<_0x45ca9f;_0x3bd902++){_0x1dcf8e+='%'+('00'+_0x553d51['charCodeAt'](_0x3bd902)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x1dcf8e);};_0x50a1['YrCsfv']=_0x290037,_0x50a1['qbalXg']={},_0x50a1['jgVQqg']=!![];}var _0x169bc0=_0x4e2a2f[0x0],_0x37920e=_0x29b023+_0x169bc0,_0x211344=_0x50a1['qbalXg'][_0x37920e];return!_0x211344?(_0x50a18d=_0x50a1['YrCsfv'](_0x50a18d),_0x50a1['qbalXg'][_0x37920e]=_0x50a18d):_0x50a18d=_0x211344,_0x50a18d;}(function(_0x41eaa3,_0x46e2cd){var _0x662fb1=_0x50a1,_0x5f082b=_0x41eaa3();while(!![]){try{var _0x72946a=-parseInt(_0x662fb1(0x1cb))/0x1+parseInt(_0x662fb1(0x1cc))/0x2*(parseInt(_0x662fb1(0x1c5))/0x3)+-parseInt(_0x662fb1(0x1d0))/0x4+parseInt(_0x662fb1(0x1ce))/0x5*(-parseInt(_0x662fb1(0x1c7))/0x6)+parseInt(_0x662fb1(0x1c8))/0x7*(-parseInt(_0x662fb1(0x1cf))/0x8)+parseInt(_0x662fb1(0x1d1))/0x9+parseInt(_0x662fb1(0x1c9))/0xa;if(_0x72946a===_0x46e2cd)break;else _0x5f082b['push'](_0x5f082b['shift']());}catch(_0x205b31){_0x5f082b['push'](_0x5f082b['shift']());}}}(_0x4e2a,0x432db));import{EvmAnchorProvider}from'./evm.js';export class BSCAnchorProvider extends EvmAnchorProvider{static ['DEFAULT_RPC_URL']=_0x3d61eb(0x1cd);constructor(_0x118851){var _0x150b00=_0x3d61eb,_0x3d78db={};_0x3d78db['rpcUrl']=_0x118851?.['rpcUrl']??BSCAnchorProvider['DEFAULT_RPC_URL'],_0x3d78db['privateKey']=_0x118851?.['privateKey'],super(_0x150b00(0x1ca),_0x150b00(0x1c6),_0x3d78db);}}function _0x4e2a(){var _0x4206bf=['mJe2nte0zxbQBuD5','mJu1nejUuNP1Aq','Ahr0Chm6lY9IC2mTzgf0yxnLzwqUyMLUyw5Jzs5VCMC','ntC5nwPitgToEG','mtCZotuXmKjmr0fjEG','mti5ntK2nffftenxBq','mtm5ntCWmNn6Ahngza','mJi4wwX2AhbY','yNnJ','mJq1nfbMu1fvAq','n1n5zejUDW','mti1ntaWodb2vu5nzxa','qLnd'];_0x4e2a=function(){return _0x4206bf;};return _0x4e2a();}
@@ -1 +1 @@
1
- const _0x4453f2=_0x43c9;(function(_0x3f5342,_0x1a7774){const _0x758faa=_0x43c9,_0x28208e=_0x3f5342();while(!![]){try{const _0x20a1c2=-parseInt(_0x758faa(0x1b1))/0x1+parseInt(_0x758faa(0x1ab))/0x2+-parseInt(_0x758faa(0x1bf))/0x3*(-parseInt(_0x758faa(0x1a8))/0x4)+-parseInt(_0x758faa(0x1ac))/0x5*(-parseInt(_0x758faa(0x1c2))/0x6)+-parseInt(_0x758faa(0x1c6))/0x7*(parseInt(_0x758faa(0x1b7))/0x8)+-parseInt(_0x758faa(0x1cf))/0x9*(parseInt(_0x758faa(0x1ca))/0xa)+parseInt(_0x758faa(0x1bd))/0xb*(parseInt(_0x758faa(0x1a7))/0xc);if(_0x20a1c2===_0x1a7774)break;else _0x28208e['push'](_0x28208e['shift']());}catch(_0x57acdd){_0x28208e['push'](_0x28208e['shift']());}}}(_0x5e2b,0x1fc88));import{ethers}from'ethers';function _0x5e2b(){const _0x39e13a=['zwXls2K','mZmXmJyZuwjOsKPP','yMXVy2TuAw1LC3rHBxa','rMzmB1O','sgfZAcbTyxrJAgvZig9UlwnOywLUigrHDge','sNnVBLjWy1bYB3zPzgvY','BwvZC2fNzq','yMfgu04','yMXVy2ToDw1Izxi','AxnbDMfPBgfIBgu','mta2ohPOEvn5Ba','ntmXnZmYEvnSvMPe','vhjHBNnHy3rPB24Gzgf0ysbKB2vZig5VDcbJB250ywLUigeGDMfSAwqGyw5JAg9Y','DMvYAwz5','mJi3mZe0v3zUrhLi','mtbOsxzmwNG','EK10BM0','DhHiyxnO','yw5JAg9Y','C3rHCNrZv2L0Aa','nZGYmtLSBevLv2y','vhjHBNnHy3rPB24GBM90igzVDw5K','C2vUzfrYyw5Zywn0Aw9U','zgf0yq','uurUuxK','BgvUz3rO','oejerNnIuG','y2HHAw4','Dg9vDgy4qNL0zxm','z2v0qMXVy2S','BMfTzq','BM93','mZC3nJnYthPgyxy','vMvYAwzPy2f0Aw9UigvYCM9YoIa','m0nHyKzQBW','AvbHwgu','AgfZAa','otaWodrjverbtMq','ChjVDMLKzxi','zgv0ywLS','D2fSBgv0','mtmYodaXowPiCufTAW','ChjPDMf0zuTLEq','v2fSBgv0','vhD4qMq','ntbdzxrJruG','zw5JB2rLrgf0yq','DgLTzxn0yw1W','DMfSAwq'];_0x5e2b=function(){return _0x39e13a;};return _0x5e2b();}const ANCHOR_PREFIX='ATEL_ANCHOR:';function _0x43c9(_0x42d499,_0x508e5a){_0x42d499=_0x42d499-0x1a1;const _0x5e2b81=_0x5e2b();let _0x43c93b=_0x5e2b81[_0x42d499];if(_0x43c9['pebWnQ']===undefined){var _0x3a6046=function(_0x525823){const _0x3d22b5='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x4473b5='',_0x456f05='';for(let _0x4cde15=0x0,_0x417fc5,_0xa07ff9,_0x4aff6e=0x0;_0xa07ff9=_0x525823['charAt'](_0x4aff6e++);~_0xa07ff9&&(_0x417fc5=_0x4cde15%0x4?_0x417fc5*0x40+_0xa07ff9:_0xa07ff9,_0x4cde15++%0x4)?_0x4473b5+=String['fromCharCode'](0xff&_0x417fc5>>(-0x2*_0x4cde15&0x6)):0x0){_0xa07ff9=_0x3d22b5['indexOf'](_0xa07ff9);}for(let _0x1c6bae=0x0,_0x503b51=_0x4473b5['length'];_0x1c6bae<_0x503b51;_0x1c6bae++){_0x456f05+='%'+('00'+_0x4473b5['charCodeAt'](_0x1c6bae)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x456f05);};_0x43c9['ZHBwdP']=_0x3a6046,_0x43c9['jeJUzf']={},_0x43c9['pebWnQ']=!![];}const _0x937f7f=_0x5e2b81[0x0],_0x4278fc=_0x42d499+_0x937f7f,_0x994542=_0x43c9['jeJUzf'][_0x4278fc];return!_0x994542?(_0x43c93b=_0x43c9['ZHBwdP'](_0x43c93b),_0x43c9['jeJUzf'][_0x4278fc]=_0x43c93b):_0x43c93b=_0x994542,_0x43c93b;}export class EvmAnchorProvider{[_0x4453f2(0x1bb)];[_0x4453f2(0x1b8)];[_0x4453f2(0x1c3)];[_0x4453f2(0x1c5)];constructor(_0xf3eb81,_0x2e95e6,_0x940d82){const _0x477328=_0x4453f2;this['name']=_0xf3eb81,this[_0x477328(0x1b8)]=_0x2e95e6,this[_0x477328(0x1c3)]=new ethers[(_0x477328(0x1a2))](_0x940d82['rpcUrl']),_0x940d82[_0x477328(0x1c7)]&&(this[_0x477328(0x1c5)]=new ethers[(_0x477328(0x1c8))](_0x940d82['privateKey'],this[_0x477328(0x1c3)]));}static['encodeData'](_0x5d43db){const _0x5856b0=_0x4453f2;return ethers['hexlify'](ethers[_0x5856b0(0x1b9)](''+ANCHOR_PREFIX+_0x5d43db));}static['decodeData'](_0x28a5d4){const _0x10062c=_0x4453f2;try{const _0x35fd6a=ethers['toUtf8String'](_0x28a5d4);if(_0x35fd6a[_0x10062c(0x1b0)](ANCHOR_PREFIX))return _0x35fd6a['slice'](ANCHOR_PREFIX[_0x10062c(0x1b6)]);return null;}catch{return null;}}async[_0x4453f2(0x1af)](_0xe59234,_0x4b0b4a){const _0x3ec56a=_0x4453f2,_0x3109f2={'xVgmw':function(_0x2e016c,_0xb46c8a){return _0x2e016c===_0xb46c8a;},'TwxBd':'svUMZ','zMtnm':'Transaction\x20receipt\x20is\x20null\x20—\x20tx\x20may\x20have\x20been\x20dropped','QDnQy':function(_0x2e9966,_0x30d6c4){return _0x2e9966 instanceof _0x30d6c4;},'FfLoZ':function(_0x14eda7,_0x2065e2){return _0x14eda7(_0x2065e2);}};if(!this[_0x3ec56a(0x1c5)])throw new Error(this[_0x3ec56a(0x1bb)]+':\x20Cannot\x20anchor\x20without\x20a\x20private\x20key');const _0x9fc4e5=EvmAnchorProvider[_0x3ec56a(0x1cb)](_0xe59234);try{const _0x172212=await this[_0x3ec56a(0x1c5)][_0x3ec56a(0x1b3)]({'to':this[_0x3ec56a(0x1c5)]['address'],'value':0x0n,'data':_0x9fc4e5}),_0x2fa34c=await _0x172212['wait']();if(!_0x2fa34c){if(_0x3109f2['xVgmw'](_0x3ec56a(0x1c0),_0x3109f2[_0x3ec56a(0x1c9)]))return![];else throw new Error(_0x3109f2[_0x3ec56a(0x1ad)]);}return{'hash':_0xe59234,'txHash':_0x2fa34c[_0x3ec56a(0x1c1)],'chain':this['chain'],'timestamp':Date[_0x3ec56a(0x1bc)](),'blockNumber':_0x2fa34c[_0x3ec56a(0x1a5)],'metadata':_0x4b0b4a};}catch(_0x365e3b){const _0x10d38e=_0x3109f2[_0x3ec56a(0x1b5)](_0x365e3b,Error)?_0x365e3b['message']:_0x3109f2[_0x3ec56a(0x1d1)](String,_0x365e3b);throw new Error(this[_0x3ec56a(0x1bb)]+'\x20anchor\x20failed:\x20'+_0x10d38e);}}async[_0x4453f2(0x1aa)](_0x32c99f,_0x515394){const _0x154673=_0x4453f2,_0x277f92={'CEsQH':function(_0x460581,_0x5d810a){return _0x460581===_0x5d810a;},'jeJqZ':_0x154673(0x1a4),'hKjLw':_0x154673(0x1b2),'jMRhX':function(_0x14ed94,_0x71a87d){return _0x14ed94===_0x71a87d;},'jMhEU':function(_0x46c0e3,_0x33f7f9){return _0x46c0e3===_0x33f7f9;},'AWmyz':function(_0x357dbb,_0x3d6bbd){return _0x357dbb*_0x3d6bbd;},'CrCQC':_0x154673(0x1a1),'elKKi':function(_0x3c7c15,_0x4baf75){return _0x3c7c15(_0x4baf75);}};try{const _0x4bd082=await this[_0x154673(0x1c3)]['getTransaction'](_0x515394);if(!_0x4bd082){if(_0x277f92['CEsQH'](_0x277f92['jeJqZ'],'baFSN')){const _0x188cb1={};return _0x188cb1['valid']=![],_0x188cb1['hash']=_0x32c99f,_0x188cb1[_0x154673(0x1ae)]=_0x515394,_0x188cb1[_0x154673(0x1b8)]=this[_0x154673(0x1b8)],_0x188cb1['detail']=_0x277f92['hKjLw'],_0x188cb1;}else return _0x59dc21['hexlify'](_0x2bcd83[_0x154673(0x1b9)](''+_0x317bb8+_0x4e7ff9));}const _0xdab21=EvmAnchorProvider['decodeData'](_0x4bd082[_0x154673(0x1b4)]);if(_0x277f92['jMRhX'](_0xdab21,null)){const _0x34bf10={};return _0x34bf10[_0x154673(0x1cd)]=![],_0x34bf10['hash']=_0x32c99f,_0x34bf10[_0x154673(0x1ae)]=_0x515394,_0x34bf10[_0x154673(0x1b8)]=this['chain'],_0x34bf10['detail']=_0x154673(0x1a9),_0x34bf10;}const _0x1aa93b=_0x277f92['jMhEU'](_0xdab21,_0x32c99f);let _0x2a93b8;if(_0x4bd082['blockNumber'])try{const _0x3f73df=await this['provider'][_0x154673(0x1ba)](_0x4bd082[_0x154673(0x1a5)]);_0x2a93b8=_0x3f73df?_0x277f92['AWmyz'](_0x3f73df[_0x154673(0x1cc)],0x3e8):undefined;}catch{}const _0x3294e6={};return _0x3294e6['valid']=_0x1aa93b,_0x3294e6['hash']=_0x32c99f,_0x3294e6['txHash']=_0x515394,_0x3294e6[_0x154673(0x1b8)]=this[_0x154673(0x1b8)],_0x3294e6[_0x154673(0x1d0)]=_0x2a93b8,_0x3294e6[_0x154673(0x1c4)]=_0x1aa93b?_0x277f92['CrCQC']:'Hash\x20mismatch:\x20expected\x20\x22'+_0x32c99f+'\x22,\x20found\x20\x22'+_0xdab21+'\x22',_0x3294e6;}catch(_0x247030){const _0x15defd=_0x247030 instanceof Error?_0x247030[_0x154673(0x1a3)]:_0x277f92[_0x154673(0x1ce)](String,_0x247030),_0x1db327={};return _0x1db327[_0x154673(0x1cd)]=![],_0x1db327[_0x154673(0x1c1)]=_0x32c99f,_0x1db327[_0x154673(0x1ae)]=_0x515394,_0x1db327['chain']=this['chain'],_0x1db327[_0x154673(0x1c4)]=_0x154673(0x1be)+_0x15defd,_0x1db327;}}async['lookup'](_0x35b85e){return[];}async[_0x4453f2(0x1a6)](){const _0x569534=_0x4453f2;try{return await this[_0x569534(0x1c3)]['getBlockNumber'](),!![];}catch{return![];}}}
1
+ const _0x3c54ba=_0x3f5a;(function(_0x5bbb88,_0x56d92c){const _0x14a661=_0x3f5a,_0x50b215=_0x5bbb88();while(!![]){try{const _0x14d427=-parseInt(_0x14a661(0xee))/0x1+parseInt(_0x14a661(0xd3))/0x2*(-parseInt(_0x14a661(0xe3))/0x3)+parseInt(_0x14a661(0xd0))/0x4*(parseInt(_0x14a661(0xf1))/0x5)+-parseInt(_0x14a661(0xf8))/0x6+-parseInt(_0x14a661(0xd1))/0x7*(-parseInt(_0x14a661(0xce))/0x8)+parseInt(_0x14a661(0xd9))/0x9*(-parseInt(_0x14a661(0xdf))/0xa)+-parseInt(_0x14a661(0xed))/0xb;if(_0x14d427===_0x56d92c)break;else _0x50b215['push'](_0x50b215['shift']());}catch(_0x589787){_0x50b215['push'](_0x50b215['shift']());}}}(_0xea0e,0x221c2));function _0x3f5a(_0x24961b,_0x5d7b09){_0x24961b=_0x24961b-0xcd;const _0xea0e02=_0xea0e();let _0x3f5a7a=_0xea0e02[_0x24961b];if(_0x3f5a['MXMKXp']===undefined){var _0x40ec30=function(_0x1a4bad){const _0x188ade='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x10b1b3='',_0x1af264='';for(let _0x2d3dd1=0x0,_0x19097c,_0x5b2fd0,_0x3dc31f=0x0;_0x5b2fd0=_0x1a4bad['charAt'](_0x3dc31f++);~_0x5b2fd0&&(_0x19097c=_0x2d3dd1%0x4?_0x19097c*0x40+_0x5b2fd0:_0x5b2fd0,_0x2d3dd1++%0x4)?_0x10b1b3+=String['fromCharCode'](0xff&_0x19097c>>(-0x2*_0x2d3dd1&0x6)):0x0){_0x5b2fd0=_0x188ade['indexOf'](_0x5b2fd0);}for(let _0x5e4f62=0x0,_0x4bf20c=_0x10b1b3['length'];_0x5e4f62<_0x4bf20c;_0x5e4f62++){_0x1af264+='%'+('00'+_0x10b1b3['charCodeAt'](_0x5e4f62)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x1af264);};_0x3f5a['pcznLR']=_0x40ec30,_0x3f5a['ACUomD']={},_0x3f5a['MXMKXp']=!![];}const _0x3a70ce=_0xea0e02[0x0],_0x31af21=_0x24961b+_0x3a70ce,_0x3d2fa7=_0x3f5a['ACUomD'][_0x31af21];return!_0x3d2fa7?(_0x3f5a7a=_0x3f5a['pcznLR'](_0x3f5a7a),_0x3f5a['ACUomD'][_0x31af21]=_0x3f5a7a):_0x3f5a7a=_0x3d2fa7,_0x3f5a7a;}import{ethers}from'ethers';function _0xea0e(){const _0x459b17=['D2fPDa','BgvUz3rO','ournzvz5BW','iIWGzM91BMqGiG','sgfZAcbTAxnTyxrJAdOGzxHWzwn0zwqGiG','sNnVBLjWy1bYB3zPzgvY','zw5JB2rLrgf0yq','AgfZAa','mJqZmdbpB0HSre4','BMfTzq','ChjPDMf0zuTLEq','z2v0qMXVy2ToDw1Izxi','odG0mJjNAujStMK','vMvYAwzPy2f0Aw9UigvYCM9YoIa','y2HHAw4','CNbJvxjS','zgf0yq','r0TMwMu','yMXVy2TuAw1LC3rHBxa','D2fSBgv0','ChjVDMLKzxi','senKu1G','mty0odiXoejhEu5mtG','mteYndmXvgnqsxb5','Bg9VA3vW','yMXVy2ToDw1Izxi','nvDmCe9NBq','qvrftf9btKnit1i6','DgLTzxn0yw1W','qMzXsgS','ywrKCMvZCW','DhHiyxnO','igfUy2HVCIbMywLSzwq6ia','ndyXmJe0zvzLBujh','BwvZC2fNzq','ogXUzM9trq','DMfSAwq','mta1mJi1mKHgAwjTvq','mtCZmZG1mvD0zvLkAG','z2v0qMXVy2S','mKf5rhDsBG','zgvJB2rLrgf0yq','zgv0ywLS','oIbdyw5UB3qGyw5JAg9YihDPDgHVDxqGysbWCML2yxrLigTLEq'];_0xea0e=function(){return _0x459b17;};return _0xea0e();}const ANCHOR_PREFIX=_0x3c54ba(0xf2);export class EvmAnchorProvider{[_0x3c54ba(0xe0)];['chain'];[_0x3c54ba(0xeb)];[_0x3c54ba(0xea)];constructor(_0x54b1c0,_0x81538,_0x42f4b8){const _0x181ca4=_0x3c54ba;this[_0x181ca4(0xe0)]=_0x54b1c0,this[_0x181ca4(0xe5)]=_0x81538,this['provider']=new ethers[(_0x181ca4(0xdc))](_0x42f4b8[_0x181ca4(0xe6)]),_0x42f4b8[_0x181ca4(0xe1)]&&(this[_0x181ca4(0xea)]=new ethers['Wallet'](_0x42f4b8['privateKey'],this[_0x181ca4(0xeb)]));}static[_0x3c54ba(0xdd)](_0x2416af){return ethers['hexlify'](ethers['toUtf8Bytes'](''+ANCHOR_PREFIX+_0x2416af));}static[_0x3c54ba(0xd4)](_0xe0a2bf){const _0x348f47=_0x3c54ba,_0xb6455a={};_0xb6455a['EPBAp']=_0x348f47(0xf4);const _0x4f4e4a=_0xb6455a;try{if('BfqHk'===_0x4f4e4a['EPBAp']){const _0x29c8c0=ethers['toUtf8String'](_0xe0a2bf);if(_0x29c8c0['startsWith'](ANCHOR_PREFIX))return _0x29c8c0['slice'](ANCHOR_PREFIX[_0x348f47(0xd8)]);return null;}else return[];}catch{return null;}}async['anchor'](_0x4667e8,_0x5acd2c){const _0x16ae51=_0x3c54ba;if(!this[_0x16ae51(0xea)])throw new Error(this[_0x16ae51(0xe0)]+_0x16ae51(0xd6));const _0x15be0d=EvmAnchorProvider[_0x16ae51(0xdd)](_0x4667e8);try{const _0x2ad970=await this['wallet']['sendTransaction']({'to':this[_0x16ae51(0xea)][_0x16ae51(0xf5)],'value':0x0n,'data':_0x15be0d}),_0x2d39f0=await _0x2ad970[_0x16ae51(0xd7)]();if(!_0x2d39f0)throw new Error('Transaction\x20receipt\x20is\x20null\x20—\x20tx\x20may\x20have\x20been\x20dropped');return{'hash':_0x4667e8,'txHash':_0x2d39f0[_0x16ae51(0xde)],'chain':this['chain'],'timestamp':Date['now'](),'blockNumber':_0x2d39f0['blockNumber'],'metadata':_0x5acd2c};}catch(_0x217977){const _0x37884d=_0x217977 instanceof Error?_0x217977['message']:String(_0x217977);throw new Error(this['name']+_0x16ae51(0xf7)+_0x37884d);}}async['verify'](_0x508a2f,_0x4fee65){const _0x16b05c=_0x3c54ba,_0x8cf615={'YmoSe':'Transaction\x20not\x20found','tFMel':function(_0x5bd2df,_0x2cb535){return _0x5bd2df===_0x2cb535;},'KYstZ':function(_0x564513,_0x196a36){return _0x564513*_0x196a36;},'ojjSq':function(_0x110c76,_0x32d36e){return _0x110c76 instanceof _0x32d36e;},'HCdSX':function(_0x1e4747,_0x2e17dd){return _0x1e4747(_0x2e17dd);}};try{const _0x462911=await this['provider']['getTransaction'](_0x4fee65);if(!_0x462911){const _0x2e610b={};return _0x2e610b[_0x16b05c(0xcf)]=![],_0x2e610b[_0x16b05c(0xde)]=_0x508a2f,_0x2e610b['txHash']=_0x4fee65,_0x2e610b[_0x16b05c(0xe5)]=this[_0x16b05c(0xe5)],_0x2e610b[_0x16b05c(0xd5)]=_0x8cf615['YmoSe'],_0x2e610b;}const _0x3e31dd=EvmAnchorProvider[_0x16b05c(0xd4)](_0x462911[_0x16b05c(0xe7)]);if(_0x8cf615['tFMel'](_0x3e31dd,null)){const _0x4c22d6={};return _0x4c22d6['valid']=![],_0x4c22d6[_0x16b05c(0xde)]=_0x508a2f,_0x4c22d6['txHash']=_0x4fee65,_0x4c22d6['chain']=this[_0x16b05c(0xe5)],_0x4c22d6['detail']='Transaction\x20data\x20does\x20not\x20contain\x20a\x20valid\x20anchor',_0x4c22d6;}const _0x12bf0a=_0x3e31dd===_0x508a2f;let _0x14b65d;if(_0x462911[_0x16b05c(0xf0)])try{const _0x22f2f6=await this['provider'][_0x16b05c(0xd2)](_0x462911[_0x16b05c(0xf0)]);_0x14b65d=_0x22f2f6?_0x8cf615['KYstZ'](_0x22f2f6[_0x16b05c(0xf3)],0x3e8):undefined;}catch{}const _0x4cb2e6={};return _0x4cb2e6[_0x16b05c(0xcf)]=_0x12bf0a,_0x4cb2e6[_0x16b05c(0xde)]=_0x508a2f,_0x4cb2e6[_0x16b05c(0xf6)]=_0x4fee65,_0x4cb2e6['chain']=this[_0x16b05c(0xe5)],_0x4cb2e6[_0x16b05c(0xe9)]=_0x14b65d,_0x4cb2e6[_0x16b05c(0xd5)]=_0x12bf0a?'Hash\x20matches\x20on-chain\x20data':_0x16b05c(0xdb)+_0x508a2f+_0x16b05c(0xda)+_0x3e31dd+'\x22',_0x4cb2e6;}catch(_0x12f3dd){if(_0x16b05c(0xe8)==='GKfZe'){const _0x1e19c4=_0x8cf615['ojjSq'](_0x12f3dd,Error)?_0x12f3dd[_0x16b05c(0xcd)]:_0x8cf615[_0x16b05c(0xec)](String,_0x12f3dd),_0x209837={};return _0x209837[_0x16b05c(0xcf)]=![],_0x209837['hash']=_0x508a2f,_0x209837[_0x16b05c(0xf6)]=_0x4fee65,_0x209837[_0x16b05c(0xe5)]=this[_0x16b05c(0xe5)],_0x209837[_0x16b05c(0xd5)]=_0x16b05c(0xe4)+_0x1e19c4,_0x209837;}else return _0x329bbc['slice'](_0x45ffcf['length']);}}async[_0x3c54ba(0xef)](_0x18c565){return[];}async['isAvailable'](){const _0x57c67a=_0x3c54ba;try{return await this['provider'][_0x57c67a(0xe2)](),!![];}catch{return![];}}}