chainlesschain 0.51.0 → 0.81.0
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/package.json +1 -1
- package/src/assets/web-panel/.build-hash +1 -1
- package/src/assets/web-panel/assets/{AppLayout-Rvi759IS.js → AppLayout-6SPt_8Y_.js} +1 -1
- package/src/assets/web-panel/assets/{Dashboard-DBhFxXYQ.js → Dashboard-Br7kCwKJ.js} +2 -2
- package/src/assets/web-panel/assets/Dashboard-CKeMmCoT.css +1 -0
- package/src/assets/web-panel/assets/{index-uL0cZ8N_.js → index-tN-8TosE.js} +2 -2
- package/src/assets/web-panel/index.html +2 -2
- package/src/commands/a2a.js +380 -0
- package/src/commands/agent-network.js +785 -0
- package/src/commands/automation.js +654 -0
- package/src/commands/bi.js +348 -0
- package/src/commands/crosschain.js +218 -0
- package/src/commands/dao.js +565 -0
- package/src/commands/did-v2.js +620 -0
- package/src/commands/dlp.js +341 -0
- package/src/commands/economy.js +578 -0
- package/src/commands/evolution.js +391 -0
- package/src/commands/evomap.js +394 -0
- package/src/commands/federation.js +283 -0
- package/src/commands/hmemory.js +442 -0
- package/src/commands/inference.js +318 -0
- package/src/commands/lowcode.js +356 -0
- package/src/commands/marketplace.js +256 -0
- package/src/commands/perf.js +433 -0
- package/src/commands/pipeline.js +449 -0
- package/src/commands/plugin-ecosystem.js +517 -0
- package/src/commands/privacy.js +321 -0
- package/src/commands/reputation.js +261 -0
- package/src/commands/sandbox.js +401 -0
- package/src/commands/siem.js +246 -0
- package/src/commands/sla.js +259 -0
- package/src/commands/social.js +311 -0
- package/src/commands/sso.js +798 -0
- package/src/commands/stress.js +230 -0
- package/src/commands/terraform.js +245 -0
- package/src/commands/workflow.js +320 -0
- package/src/commands/zkp.js +562 -1
- package/src/index.js +21 -0
- package/src/lib/a2a-protocol.js +451 -0
- package/src/lib/agent-economy.js +479 -0
- package/src/lib/agent-network.js +1121 -0
- package/src/lib/app-builder.js +239 -0
- package/src/lib/automation-engine.js +948 -0
- package/src/lib/bi-engine.js +338 -0
- package/src/lib/cross-chain.js +345 -0
- package/src/lib/dao-governance.js +569 -0
- package/src/lib/did-v2-manager.js +1127 -0
- package/src/lib/dlp-engine.js +389 -0
- package/src/lib/evolution-system.js +453 -0
- package/src/lib/evomap-federation.js +177 -0
- package/src/lib/evomap-governance.js +276 -0
- package/src/lib/federation-hardening.js +259 -0
- package/src/lib/hierarchical-memory.js +481 -0
- package/src/lib/inference-network.js +330 -0
- package/src/lib/perf-tuning.js +734 -0
- package/src/lib/pipeline-orchestrator.js +928 -0
- package/src/lib/plugin-ecosystem.js +1109 -0
- package/src/lib/privacy-computing.js +427 -0
- package/src/lib/reputation-optimizer.js +299 -0
- package/src/lib/sandbox-v2.js +306 -0
- package/src/lib/siem-exporter.js +333 -0
- package/src/lib/skill-marketplace.js +325 -0
- package/src/lib/sla-manager.js +275 -0
- package/src/lib/social-graph-analytics.js +707 -0
- package/src/lib/sso-manager.js +841 -0
- package/src/lib/stress-tester.js +330 -0
- package/src/lib/terraform-manager.js +363 -0
- package/src/lib/workflow-engine.js +454 -1
- package/src/lib/zkp-engine.js +523 -20
- package/src/assets/web-panel/assets/Dashboard-BS-tzGNj.css +0 -1
package/src/lib/zkp-engine.js
CHANGED
|
@@ -1,16 +1,34 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* ZKP Engine — Zero-knowledge proof circuit compilation, proof generation,
|
|
3
|
-
* verification, and selective identity disclosure.
|
|
3
|
+
* verification, and selective identity disclosure (Phase 88).
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import crypto from "crypto";
|
|
7
7
|
|
|
8
|
+
/* ── Phase 88 frozen enums ─────────────────────────────────── */
|
|
9
|
+
|
|
10
|
+
export const PROOF_SCHEME = Object.freeze({
|
|
11
|
+
GROTH16: "groth16",
|
|
12
|
+
PLONK: "plonk",
|
|
13
|
+
BULLETPROOFS: "bulletproofs",
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
export const CIRCUIT_STATUS = Object.freeze({
|
|
17
|
+
DRAFT: "draft",
|
|
18
|
+
COMPILED: "compiled",
|
|
19
|
+
VERIFIED: "verified",
|
|
20
|
+
FAILED: "failed",
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
export const SUPPORTED_SCHEMES = new Set(Object.values(PROOF_SCHEME));
|
|
24
|
+
|
|
8
25
|
/* ── In-memory stores ──────────────────────────────────────── */
|
|
9
26
|
const _circuits = new Map();
|
|
10
27
|
const _proofs = new Map();
|
|
11
28
|
const _verificationKeys = new Map();
|
|
29
|
+
const _credentials = new Map();
|
|
12
30
|
|
|
13
|
-
const DEFAULT_SCHEME =
|
|
31
|
+
const DEFAULT_SCHEME = PROOF_SCHEME.GROTH16;
|
|
14
32
|
|
|
15
33
|
/* ── Schema ────────────────────────────────────────────────── */
|
|
16
34
|
|
|
@@ -22,6 +40,7 @@ export function ensureZKPTables(db) {
|
|
|
22
40
|
definition TEXT,
|
|
23
41
|
compiled TEXT,
|
|
24
42
|
verification_key TEXT,
|
|
43
|
+
status TEXT DEFAULT 'draft',
|
|
25
44
|
created_at TEXT DEFAULT (datetime('now'))
|
|
26
45
|
)
|
|
27
46
|
`);
|
|
@@ -36,6 +55,15 @@ export function ensureZKPTables(db) {
|
|
|
36
55
|
created_at TEXT DEFAULT (datetime('now'))
|
|
37
56
|
)
|
|
38
57
|
`);
|
|
58
|
+
db.exec(`
|
|
59
|
+
CREATE TABLE IF NOT EXISTS zkp_credentials (
|
|
60
|
+
id TEXT PRIMARY KEY,
|
|
61
|
+
did TEXT,
|
|
62
|
+
claims TEXT NOT NULL,
|
|
63
|
+
merkle_root TEXT NOT NULL,
|
|
64
|
+
created_at TEXT DEFAULT (datetime('now'))
|
|
65
|
+
)
|
|
66
|
+
`);
|
|
39
67
|
}
|
|
40
68
|
|
|
41
69
|
/* ── Circuit Compilation ───────────────────────────────────── */
|
|
@@ -82,6 +110,7 @@ export function compileCircuit(db, name, definition) {
|
|
|
82
110
|
inputs,
|
|
83
111
|
outputs,
|
|
84
112
|
verificationKey,
|
|
113
|
+
status: CIRCUIT_STATUS.COMPILED,
|
|
85
114
|
createdAt: now,
|
|
86
115
|
};
|
|
87
116
|
|
|
@@ -89,40 +118,87 @@ export function compileCircuit(db, name, definition) {
|
|
|
89
118
|
_verificationKeys.set(id, verificationKey);
|
|
90
119
|
|
|
91
120
|
db.prepare(
|
|
92
|
-
`INSERT INTO zkp_circuits (id, name, definition, compiled, verification_key, created_at)
|
|
93
|
-
VALUES (?, ?, ?, ?, ?, ?)`,
|
|
121
|
+
`INSERT INTO zkp_circuits (id, name, definition, compiled, verification_key, status, created_at)
|
|
122
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)`,
|
|
94
123
|
).run(
|
|
95
124
|
id,
|
|
96
125
|
name,
|
|
97
126
|
JSON.stringify(parsed),
|
|
98
127
|
JSON.stringify(compiled),
|
|
99
128
|
verificationKey,
|
|
129
|
+
CIRCUIT_STATUS.COMPILED,
|
|
100
130
|
now,
|
|
101
131
|
);
|
|
102
132
|
|
|
103
133
|
return circuit;
|
|
104
134
|
}
|
|
105
135
|
|
|
136
|
+
/**
|
|
137
|
+
* Update a circuit's status (DRAFT / COMPILED / VERIFIED / FAILED).
|
|
138
|
+
*/
|
|
139
|
+
export function setCircuitStatus(db, circuitId, status) {
|
|
140
|
+
if (!Object.values(CIRCUIT_STATUS).includes(status)) {
|
|
141
|
+
throw new Error(`Invalid circuit status: ${status}`);
|
|
142
|
+
}
|
|
143
|
+
const circuit = _circuits.get(circuitId);
|
|
144
|
+
if (!circuit) throw new Error(`Circuit not found: ${circuitId}`);
|
|
145
|
+
circuit.status = status;
|
|
146
|
+
db.prepare("UPDATE zkp_circuits SET status = ? WHERE id = ?").run(
|
|
147
|
+
status,
|
|
148
|
+
circuitId,
|
|
149
|
+
);
|
|
150
|
+
return { id: circuitId, status };
|
|
151
|
+
}
|
|
152
|
+
|
|
106
153
|
/* ── Proof Generation ──────────────────────────────────────── */
|
|
107
154
|
|
|
108
|
-
export function generateProof(
|
|
155
|
+
export function generateProof(
|
|
156
|
+
db,
|
|
157
|
+
circuitId,
|
|
158
|
+
privateInputs,
|
|
159
|
+
publicInputs,
|
|
160
|
+
options = {},
|
|
161
|
+
) {
|
|
109
162
|
const circuit = _circuits.get(circuitId);
|
|
110
163
|
if (!circuit) throw new Error(`Circuit not found: ${circuitId}`);
|
|
111
164
|
|
|
165
|
+
const scheme = options.scheme || DEFAULT_SCHEME;
|
|
166
|
+
if (!SUPPORTED_SCHEMES.has(scheme)) {
|
|
167
|
+
throw new Error(
|
|
168
|
+
`Unsupported proof scheme: ${scheme}. Supported: ${[...SUPPORTED_SCHEMES].join(", ")}`,
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
|
|
112
172
|
const id = crypto.randomUUID();
|
|
113
173
|
const now = new Date().toISOString();
|
|
114
174
|
|
|
115
|
-
//
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
175
|
+
// Scheme-shaped mock proof structure
|
|
176
|
+
let proofData;
|
|
177
|
+
if (scheme === PROOF_SCHEME.GROTH16) {
|
|
178
|
+
proofData = {
|
|
179
|
+
a: crypto.randomBytes(32).toString("hex"),
|
|
180
|
+
b: crypto.randomBytes(64).toString("hex"),
|
|
181
|
+
c: crypto.randomBytes(32).toString("hex"),
|
|
182
|
+
};
|
|
183
|
+
} else if (scheme === PROOF_SCHEME.PLONK) {
|
|
184
|
+
proofData = {
|
|
185
|
+
commitments: crypto.randomBytes(96).toString("hex"),
|
|
186
|
+
evaluations: crypto.randomBytes(64).toString("hex"),
|
|
187
|
+
};
|
|
188
|
+
} else {
|
|
189
|
+
// bulletproofs — range proof shape
|
|
190
|
+
proofData = {
|
|
191
|
+
V: crypto.randomBytes(32).toString("hex"),
|
|
192
|
+
A: crypto.randomBytes(32).toString("hex"),
|
|
193
|
+
S: crypto.randomBytes(32).toString("hex"),
|
|
194
|
+
t1: crypto.randomBytes(32).toString("hex"),
|
|
195
|
+
};
|
|
196
|
+
}
|
|
121
197
|
|
|
122
198
|
const proof = {
|
|
123
199
|
id,
|
|
124
200
|
circuitId,
|
|
125
|
-
scheme
|
|
201
|
+
scheme,
|
|
126
202
|
proof: proofData,
|
|
127
203
|
publicInputs: publicInputs || [],
|
|
128
204
|
verified: false,
|
|
@@ -140,7 +216,7 @@ export function generateProof(db, circuitId, privateInputs, publicInputs) {
|
|
|
140
216
|
JSON.stringify(proofData),
|
|
141
217
|
JSON.stringify(publicInputs || []),
|
|
142
218
|
0,
|
|
143
|
-
|
|
219
|
+
scheme,
|
|
144
220
|
now,
|
|
145
221
|
);
|
|
146
222
|
|
|
@@ -156,13 +232,27 @@ export function verifyProof(db, proofId) {
|
|
|
156
232
|
const circuit = _circuits.get(proof.circuitId);
|
|
157
233
|
if (!circuit) throw new Error(`Circuit not found for proof: ${proofId}`);
|
|
158
234
|
|
|
159
|
-
//
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
235
|
+
// Scheme-aware structural validation
|
|
236
|
+
let structurallyValid = false;
|
|
237
|
+
if (proof.scheme === PROOF_SCHEME.GROTH16) {
|
|
238
|
+
structurallyValid =
|
|
239
|
+
proof.proof &&
|
|
240
|
+
typeof proof.proof.a === "string" &&
|
|
241
|
+
typeof proof.proof.b === "string" &&
|
|
242
|
+
typeof proof.proof.c === "string";
|
|
243
|
+
} else if (proof.scheme === PROOF_SCHEME.PLONK) {
|
|
244
|
+
structurallyValid =
|
|
245
|
+
proof.proof &&
|
|
246
|
+
typeof proof.proof.commitments === "string" &&
|
|
247
|
+
typeof proof.proof.evaluations === "string";
|
|
248
|
+
} else if (proof.scheme === PROOF_SCHEME.BULLETPROOFS) {
|
|
249
|
+
structurallyValid =
|
|
250
|
+
proof.proof &&
|
|
251
|
+
typeof proof.proof.V === "string" &&
|
|
252
|
+
typeof proof.proof.A === "string";
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
const valid = structurallyValid && _verificationKeys.has(proof.circuitId);
|
|
166
256
|
|
|
167
257
|
proof.verified = valid;
|
|
168
258
|
|
|
@@ -207,14 +297,152 @@ export function createIdentityProof(claims, disclosedFields) {
|
|
|
207
297
|
};
|
|
208
298
|
}
|
|
209
299
|
|
|
300
|
+
/* ── Credentials + Merkle-tree selective disclosure ──────────── */
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Compute a deterministic Merkle root over sorted (field, hash(value)) leaves.
|
|
304
|
+
* Each leaf = sha256(fieldName + ":" + sha256(stringified-value)).
|
|
305
|
+
* Pairs combine as sha256(left + right), odd leaves are duplicated (standard).
|
|
306
|
+
*/
|
|
307
|
+
function _merkleRoot(claims) {
|
|
308
|
+
const fields = Object.keys(claims).sort();
|
|
309
|
+
if (fields.length === 0) {
|
|
310
|
+
return crypto.createHash("sha256").update("").digest("hex");
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
let level = fields.map((field) => {
|
|
314
|
+
const valHash = crypto
|
|
315
|
+
.createHash("sha256")
|
|
316
|
+
.update(JSON.stringify(claims[field]))
|
|
317
|
+
.digest("hex");
|
|
318
|
+
return crypto
|
|
319
|
+
.createHash("sha256")
|
|
320
|
+
.update(`${field}:${valHash}`)
|
|
321
|
+
.digest("hex");
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
while (level.length > 1) {
|
|
325
|
+
const next = [];
|
|
326
|
+
for (let i = 0; i < level.length; i += 2) {
|
|
327
|
+
const left = level[i];
|
|
328
|
+
const right = i + 1 < level.length ? level[i + 1] : left;
|
|
329
|
+
next.push(
|
|
330
|
+
crypto
|
|
331
|
+
.createHash("sha256")
|
|
332
|
+
.update(left + right)
|
|
333
|
+
.digest("hex"),
|
|
334
|
+
);
|
|
335
|
+
}
|
|
336
|
+
level = next;
|
|
337
|
+
}
|
|
338
|
+
return level[0];
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Register a verifiable credential. Returns `{ id, did, merkleRoot, claims }`.
|
|
343
|
+
*/
|
|
344
|
+
export function registerCredential(db, { did, claims }) {
|
|
345
|
+
if (!claims || typeof claims !== "object") {
|
|
346
|
+
throw new Error("Claims must be an object");
|
|
347
|
+
}
|
|
348
|
+
const id = crypto.randomUUID();
|
|
349
|
+
const now = new Date().toISOString();
|
|
350
|
+
const merkleRoot = _merkleRoot(claims);
|
|
351
|
+
|
|
352
|
+
const credential = {
|
|
353
|
+
id,
|
|
354
|
+
did: did || null,
|
|
355
|
+
claims,
|
|
356
|
+
merkleRoot,
|
|
357
|
+
createdAt: now,
|
|
358
|
+
};
|
|
359
|
+
_credentials.set(id, credential);
|
|
360
|
+
|
|
361
|
+
db.prepare(
|
|
362
|
+
`INSERT INTO zkp_credentials (id, did, claims, merkle_root, created_at)
|
|
363
|
+
VALUES (?, ?, ?, ?, ?)`,
|
|
364
|
+
).run(id, did || null, JSON.stringify(claims), merkleRoot, now);
|
|
365
|
+
|
|
366
|
+
return credential;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Selectively disclose a subset of credential fields to a recipient.
|
|
371
|
+
* Returns `{ id, credentialId, recipientDid, disclosed, merkleRoot, hiddenCount }`.
|
|
372
|
+
* The receiver can recompute the Merkle root (given hashed pads for hidden fields)
|
|
373
|
+
* and match it against the credential's merkleRoot to confirm integrity.
|
|
374
|
+
*/
|
|
375
|
+
export function selectiveDisclose(
|
|
376
|
+
db,
|
|
377
|
+
credentialId,
|
|
378
|
+
disclosedFields,
|
|
379
|
+
recipientDid = null,
|
|
380
|
+
) {
|
|
381
|
+
const credential = _credentials.get(credentialId);
|
|
382
|
+
if (!credential) {
|
|
383
|
+
throw new Error(`Credential not found: ${credentialId}`);
|
|
384
|
+
}
|
|
385
|
+
if (!Array.isArray(disclosedFields)) {
|
|
386
|
+
throw new Error("disclosedFields must be an array");
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
const allFields = Object.keys(credential.claims);
|
|
390
|
+
const disclosed = {};
|
|
391
|
+
const hiddenFields = [];
|
|
392
|
+
|
|
393
|
+
for (const field of allFields) {
|
|
394
|
+
if (disclosedFields.includes(field)) {
|
|
395
|
+
disclosed[field] = credential.claims[field];
|
|
396
|
+
} else {
|
|
397
|
+
hiddenFields.push(field);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
return {
|
|
402
|
+
id: crypto.randomUUID(),
|
|
403
|
+
type: "selective-disclosure",
|
|
404
|
+
credentialId,
|
|
405
|
+
recipientDid,
|
|
406
|
+
disclosed,
|
|
407
|
+
hiddenCount: hiddenFields.length,
|
|
408
|
+
hiddenFields,
|
|
409
|
+
merkleRoot: credential.merkleRoot,
|
|
410
|
+
disclosedAt: new Date().toISOString(),
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* List registered credentials, optionally filtered by DID.
|
|
416
|
+
*/
|
|
417
|
+
export function listCredentials(db, options = {}) {
|
|
418
|
+
let creds = [..._credentials.values()];
|
|
419
|
+
if (options.did) {
|
|
420
|
+
creds = creds.filter((c) => c.did === options.did);
|
|
421
|
+
}
|
|
422
|
+
return creds;
|
|
423
|
+
}
|
|
424
|
+
|
|
210
425
|
/* ── Stats ─────────────────────────────────────────────────── */
|
|
211
426
|
|
|
212
427
|
export function getZKPStats() {
|
|
213
428
|
const proofList = [..._proofs.values()];
|
|
429
|
+
const bySchemeCount = {};
|
|
430
|
+
for (const scheme of Object.values(PROOF_SCHEME)) {
|
|
431
|
+
bySchemeCount[scheme] = proofList.filter((p) => p.scheme === scheme).length;
|
|
432
|
+
}
|
|
433
|
+
const byStatusCount = {};
|
|
434
|
+
for (const status of Object.values(CIRCUIT_STATUS)) {
|
|
435
|
+
byStatusCount[status] = [..._circuits.values()].filter(
|
|
436
|
+
(c) => c.status === status,
|
|
437
|
+
).length;
|
|
438
|
+
}
|
|
214
439
|
return {
|
|
215
440
|
circuits: _circuits.size,
|
|
216
441
|
proofs: proofList.length,
|
|
217
442
|
verifiedProofs: proofList.filter((p) => p.verified).length,
|
|
443
|
+
credentials: _credentials.size,
|
|
444
|
+
proofsByScheme: bySchemeCount,
|
|
445
|
+
circuitsByStatus: byStatusCount,
|
|
218
446
|
};
|
|
219
447
|
}
|
|
220
448
|
|
|
@@ -238,4 +466,279 @@ export function _resetState() {
|
|
|
238
466
|
_circuits.clear();
|
|
239
467
|
_proofs.clear();
|
|
240
468
|
_verificationKeys.clear();
|
|
469
|
+
_credentials.clear();
|
|
470
|
+
_maxCircuitsPerCreator = ZKP_DEFAULT_MAX_CIRCUITS_PER_CREATOR;
|
|
471
|
+
_proofExpiryMs = ZKP_DEFAULT_PROOF_EXPIRY_MS;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
/* ──────────────────────────────────────────────────────────
|
|
475
|
+
* V2 — Phase 88 surface (strictly additive)
|
|
476
|
+
* ────────────────────────────────────────────────────────── */
|
|
477
|
+
|
|
478
|
+
export const PROOF_SCHEME_V2 = PROOF_SCHEME;
|
|
479
|
+
export const CIRCUIT_STATUS_V2 = CIRCUIT_STATUS;
|
|
480
|
+
|
|
481
|
+
export const PROOF_STATUS_V2 = Object.freeze({
|
|
482
|
+
PENDING: "pending",
|
|
483
|
+
VERIFIED: "verified",
|
|
484
|
+
INVALID: "invalid",
|
|
485
|
+
EXPIRED: "expired",
|
|
486
|
+
});
|
|
487
|
+
|
|
488
|
+
export const ZKP_DEFAULT_MAX_CIRCUITS_PER_CREATOR = 10;
|
|
489
|
+
export const ZKP_DEFAULT_PROOF_EXPIRY_MS = 3600_000; // 1h
|
|
490
|
+
|
|
491
|
+
let _maxCircuitsPerCreator = ZKP_DEFAULT_MAX_CIRCUITS_PER_CREATOR;
|
|
492
|
+
let _proofExpiryMs = ZKP_DEFAULT_PROOF_EXPIRY_MS;
|
|
493
|
+
|
|
494
|
+
const CIRCUIT_TRANSITIONS_V2 = new Map([
|
|
495
|
+
["draft", new Set(["compiled", "failed"])],
|
|
496
|
+
["compiled", new Set(["verified", "failed"])],
|
|
497
|
+
]);
|
|
498
|
+
const CIRCUIT_TERMINALS_V2 = new Set(["verified", "failed"]);
|
|
499
|
+
|
|
500
|
+
const PROOF_TRANSITIONS_V2 = new Map([
|
|
501
|
+
["pending", new Set(["verified", "invalid", "expired"])],
|
|
502
|
+
]);
|
|
503
|
+
const PROOF_TERMINALS_V2 = new Set(["verified", "invalid", "expired"]);
|
|
504
|
+
|
|
505
|
+
/* ── Config ────────────────────────────────────────────── */
|
|
506
|
+
|
|
507
|
+
export function setMaxCircuitsPerCreator(n) {
|
|
508
|
+
if (typeof n !== "number" || Number.isNaN(n) || n < 1) {
|
|
509
|
+
throw new Error("maxCircuitsPerCreator must be a positive integer");
|
|
510
|
+
}
|
|
511
|
+
_maxCircuitsPerCreator = Math.floor(n);
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
export function getMaxCircuitsPerCreator() {
|
|
515
|
+
return _maxCircuitsPerCreator;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
export function getCircuitCountByCreator(creator) {
|
|
519
|
+
if (!creator) return 0;
|
|
520
|
+
let count = 0;
|
|
521
|
+
for (const c of _circuits.values()) {
|
|
522
|
+
if (c.creator === creator) count += 1;
|
|
523
|
+
}
|
|
524
|
+
return count;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
export function setProofExpiryMs(ms) {
|
|
528
|
+
if (typeof ms !== "number" || Number.isNaN(ms) || ms < 1) {
|
|
529
|
+
throw new Error("proofExpiryMs must be a positive integer");
|
|
530
|
+
}
|
|
531
|
+
_proofExpiryMs = Math.floor(ms);
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
export function getProofExpiryMs() {
|
|
535
|
+
return _proofExpiryMs;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
/* ── Circuit V2 ────────────────────────────────────────── */
|
|
539
|
+
|
|
540
|
+
export function compileCircuitV2(db, { name, definition, creator } = {}) {
|
|
541
|
+
if (!name) throw new Error("name is required");
|
|
542
|
+
if (creator) {
|
|
543
|
+
const count = getCircuitCountByCreator(creator);
|
|
544
|
+
if (count >= _maxCircuitsPerCreator) {
|
|
545
|
+
throw new Error(
|
|
546
|
+
`Max circuits per creator reached (${count}/${_maxCircuitsPerCreator})`,
|
|
547
|
+
);
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
const circuit = compileCircuit(db, name, definition);
|
|
551
|
+
if (creator) {
|
|
552
|
+
circuit.creator = creator;
|
|
553
|
+
}
|
|
554
|
+
return { ...circuit };
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
export function setCircuitStatusV2(db, circuitId, newStatus, patch = {}) {
|
|
558
|
+
const circuit = _circuits.get(circuitId);
|
|
559
|
+
if (!circuit) throw new Error(`Circuit not found: ${circuitId}`);
|
|
560
|
+
if (!Object.values(CIRCUIT_STATUS_V2).includes(newStatus)) {
|
|
561
|
+
throw new Error(`Unknown circuit status: ${newStatus}`);
|
|
562
|
+
}
|
|
563
|
+
const allowed = CIRCUIT_TRANSITIONS_V2.get(circuit.status);
|
|
564
|
+
if (!allowed || !allowed.has(newStatus)) {
|
|
565
|
+
throw new Error(`Invalid transition: ${circuit.status} → ${newStatus}`);
|
|
566
|
+
}
|
|
567
|
+
circuit.status = newStatus;
|
|
568
|
+
if (patch.errorMessage !== undefined)
|
|
569
|
+
circuit.errorMessage = patch.errorMessage;
|
|
570
|
+
db.prepare("UPDATE zkp_circuits SET status = ? WHERE id = ?").run(
|
|
571
|
+
newStatus,
|
|
572
|
+
circuitId,
|
|
573
|
+
);
|
|
574
|
+
return { ...circuit };
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
/* ── Proof V2 ──────────────────────────────────────────── */
|
|
578
|
+
|
|
579
|
+
export function generateProofV2(
|
|
580
|
+
db,
|
|
581
|
+
{ circuitId, privateInputs, publicInputs, scheme } = {},
|
|
582
|
+
) {
|
|
583
|
+
if (!circuitId) throw new Error("circuitId is required");
|
|
584
|
+
const circuit = _circuits.get(circuitId);
|
|
585
|
+
if (!circuit) throw new Error(`Circuit not found: ${circuitId}`);
|
|
586
|
+
if (
|
|
587
|
+
circuit.status !== CIRCUIT_STATUS.COMPILED &&
|
|
588
|
+
circuit.status !== CIRCUIT_STATUS.VERIFIED
|
|
589
|
+
) {
|
|
590
|
+
throw new Error(
|
|
591
|
+
`Circuit not ready (status=${circuit.status}, must be compiled/verified)`,
|
|
592
|
+
);
|
|
593
|
+
}
|
|
594
|
+
const proof = generateProof(db, circuitId, privateInputs, publicInputs, {
|
|
595
|
+
scheme,
|
|
596
|
+
});
|
|
597
|
+
const stored = _proofs.get(proof.id);
|
|
598
|
+
stored.status = PROOF_STATUS_V2.PENDING;
|
|
599
|
+
stored.expiresAt = Date.now() + _proofExpiryMs;
|
|
600
|
+
return { ...stored };
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
export function verifyProofV2(db, proofId) {
|
|
604
|
+
const proof = _proofs.get(proofId);
|
|
605
|
+
if (!proof) throw new Error(`Proof not found: ${proofId}`);
|
|
606
|
+
const current = proof.status || PROOF_STATUS_V2.PENDING;
|
|
607
|
+
if (PROOF_TERMINALS_V2.has(current)) {
|
|
608
|
+
throw new Error(`Invalid transition: ${current} → verify (terminal)`);
|
|
609
|
+
}
|
|
610
|
+
if (proof.expiresAt && Date.now() > proof.expiresAt) {
|
|
611
|
+
proof.status = PROOF_STATUS_V2.EXPIRED;
|
|
612
|
+
db.prepare("UPDATE zkp_proofs SET verified = 0 WHERE id = ?").run(proofId);
|
|
613
|
+
return { ...proof, valid: false, reason: "expired" };
|
|
614
|
+
}
|
|
615
|
+
const result = verifyProof(db, proofId);
|
|
616
|
+
proof.status = result.valid
|
|
617
|
+
? PROOF_STATUS_V2.VERIFIED
|
|
618
|
+
: PROOF_STATUS_V2.INVALID;
|
|
619
|
+
return { ...proof, valid: result.valid };
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
export function failProof(db, proofId, { reason } = {}) {
|
|
623
|
+
const proof = _proofs.get(proofId);
|
|
624
|
+
if (!proof) throw new Error(`Proof not found: ${proofId}`);
|
|
625
|
+
const current = proof.status || PROOF_STATUS_V2.PENDING;
|
|
626
|
+
if (PROOF_TERMINALS_V2.has(current)) {
|
|
627
|
+
throw new Error(`Invalid transition: ${current} → invalid (terminal)`);
|
|
628
|
+
}
|
|
629
|
+
proof.status = PROOF_STATUS_V2.INVALID;
|
|
630
|
+
proof.verified = false;
|
|
631
|
+
if (reason !== undefined) proof.errorMessage = reason;
|
|
632
|
+
db.prepare("UPDATE zkp_proofs SET verified = 0 WHERE id = ?").run(proofId);
|
|
633
|
+
return { ...proof };
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
export function setProofStatus(db, proofId, newStatus, patch = {}) {
|
|
637
|
+
const proof = _proofs.get(proofId);
|
|
638
|
+
if (!proof) throw new Error(`Proof not found: ${proofId}`);
|
|
639
|
+
if (!Object.values(PROOF_STATUS_V2).includes(newStatus)) {
|
|
640
|
+
throw new Error(`Unknown proof status: ${newStatus}`);
|
|
641
|
+
}
|
|
642
|
+
const current = proof.status || PROOF_STATUS_V2.PENDING;
|
|
643
|
+
const allowed = PROOF_TRANSITIONS_V2.get(current);
|
|
644
|
+
if (!allowed || !allowed.has(newStatus)) {
|
|
645
|
+
throw new Error(`Invalid transition: ${current} → ${newStatus}`);
|
|
646
|
+
}
|
|
647
|
+
proof.status = newStatus;
|
|
648
|
+
if (patch.errorMessage !== undefined) proof.errorMessage = patch.errorMessage;
|
|
649
|
+
if (newStatus === PROOF_STATUS_V2.VERIFIED) {
|
|
650
|
+
proof.verified = true;
|
|
651
|
+
db.prepare("UPDATE zkp_proofs SET verified = 1 WHERE id = ?").run(proofId);
|
|
652
|
+
} else {
|
|
653
|
+
proof.verified = false;
|
|
654
|
+
db.prepare("UPDATE zkp_proofs SET verified = 0 WHERE id = ?").run(proofId);
|
|
655
|
+
}
|
|
656
|
+
return { ...proof };
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
export function autoExpireProofs(db) {
|
|
660
|
+
const now = Date.now();
|
|
661
|
+
const expired = [];
|
|
662
|
+
for (const proof of _proofs.values()) {
|
|
663
|
+
const current = proof.status || PROOF_STATUS_V2.PENDING;
|
|
664
|
+
if (PROOF_TERMINALS_V2.has(current)) continue;
|
|
665
|
+
if (proof.expiresAt && now > proof.expiresAt) {
|
|
666
|
+
proof.status = PROOF_STATUS_V2.EXPIRED;
|
|
667
|
+
proof.verified = false;
|
|
668
|
+
db.prepare("UPDATE zkp_proofs SET verified = 0 WHERE id = ?").run(
|
|
669
|
+
proof.id,
|
|
670
|
+
);
|
|
671
|
+
expired.push({ ...proof });
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
return expired;
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
/* ── Selective Disclosure V2 ───────────────────────────── */
|
|
678
|
+
|
|
679
|
+
export function selectiveDiscloseV2(
|
|
680
|
+
db,
|
|
681
|
+
{ credentialId, disclosedFields, requiredFields, recipientDid } = {},
|
|
682
|
+
) {
|
|
683
|
+
if (!credentialId) throw new Error("credentialId is required");
|
|
684
|
+
if (!Array.isArray(disclosedFields)) {
|
|
685
|
+
throw new Error("disclosedFields must be an array");
|
|
686
|
+
}
|
|
687
|
+
const credential = _credentials.get(credentialId);
|
|
688
|
+
if (!credential) throw new Error(`Credential not found: ${credentialId}`);
|
|
689
|
+
if (Array.isArray(requiredFields)) {
|
|
690
|
+
for (const f of requiredFields) {
|
|
691
|
+
if (!disclosedFields.includes(f)) {
|
|
692
|
+
throw new Error(`Required field missing from disclosure: ${f}`);
|
|
693
|
+
}
|
|
694
|
+
if (!(f in credential.claims)) {
|
|
695
|
+
throw new Error(`Required field not in credential: ${f}`);
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
return selectiveDisclose(db, credentialId, disclosedFields, recipientDid);
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
/* ── V2 Stats ──────────────────────────────────────────── */
|
|
703
|
+
|
|
704
|
+
export function getZKPStatsV2() {
|
|
705
|
+
const circuitsByStatus = {};
|
|
706
|
+
for (const s of Object.values(CIRCUIT_STATUS_V2)) circuitsByStatus[s] = 0;
|
|
707
|
+
const proofsByStatus = {};
|
|
708
|
+
for (const s of Object.values(PROOF_STATUS_V2)) proofsByStatus[s] = 0;
|
|
709
|
+
const proofsByScheme = {};
|
|
710
|
+
for (const s of Object.values(PROOF_SCHEME_V2)) proofsByScheme[s] = 0;
|
|
711
|
+
|
|
712
|
+
for (const c of _circuits.values()) {
|
|
713
|
+
circuitsByStatus[c.status] = (circuitsByStatus[c.status] || 0) + 1;
|
|
714
|
+
}
|
|
715
|
+
let verifiedCount = 0;
|
|
716
|
+
let pendingCount = 0;
|
|
717
|
+
for (const p of _proofs.values()) {
|
|
718
|
+
const status = p.status || PROOF_STATUS_V2.PENDING;
|
|
719
|
+
proofsByStatus[status] = (proofsByStatus[status] || 0) + 1;
|
|
720
|
+
proofsByScheme[p.scheme] = (proofsByScheme[p.scheme] || 0) + 1;
|
|
721
|
+
if (status === PROOF_STATUS_V2.VERIFIED) verifiedCount += 1;
|
|
722
|
+
if (status === PROOF_STATUS_V2.PENDING) pendingCount += 1;
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
const credentialsByDid = {};
|
|
726
|
+
for (const c of _credentials.values()) {
|
|
727
|
+
const key = c.did || "_anonymous";
|
|
728
|
+
credentialsByDid[key] = (credentialsByDid[key] || 0) + 1;
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
return {
|
|
732
|
+
totalCircuits: _circuits.size,
|
|
733
|
+
totalProofs: _proofs.size,
|
|
734
|
+
totalCredentials: _credentials.size,
|
|
735
|
+
verifiedProofs: verifiedCount,
|
|
736
|
+
pendingProofs: pendingCount,
|
|
737
|
+
maxCircuitsPerCreator: _maxCircuitsPerCreator,
|
|
738
|
+
proofExpiryMs: _proofExpiryMs,
|
|
739
|
+
circuitsByStatus,
|
|
740
|
+
proofsByStatus,
|
|
741
|
+
proofsByScheme,
|
|
742
|
+
credentialsByDid,
|
|
743
|
+
};
|
|
241
744
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.stat-card[data-v-39c5aabc]{background:var(--bg-card)!important;border-color:var(--border-color)!important;transition:border-color .2s}.stat-card[data-v-39c5aabc]:hover{border-color:var(--text-muted)!important}.stat-header[data-v-39c5aabc]{display:flex;justify-content:space-between;align-items:center;margin-bottom:6px}.stat-label[data-v-39c5aabc]{color:var(--text-secondary);font-size:12px}.stat-value[data-v-39c5aabc]{font-size:22px;font-weight:600;line-height:1.2;margin-bottom:4px}.stat-sub[data-v-39c5aabc]{color:var(--text-muted);font-size:11px}.gateway-card[data-v-39c5aabc]{border-left:3px solid #1677ff!important}.status-log[data-v-39c5aabc]{background:var(--bg-base);border:1px solid var(--border-color);border-radius:6px;padding:10px 14px;color:var(--text-secondary);font-size:11px;font-family:Consolas,monospace;max-height:200px;overflow-y:auto;white-space:pre-wrap;margin:0;line-height:1.6}.telemetry-card[data-v-39c5aabc]{background:var(--bg-base);border:1px solid var(--border-color);border-radius:8px;padding:14px;height:100%}.telemetry-filter[data-v-39c5aabc]{display:flex;flex-direction:column;gap:6px}.telemetry-filter-label[data-v-39c5aabc]{color:var(--text-muted);font-size:12px}.telemetry-label[data-v-39c5aabc]{color:var(--text-muted);font-size:12px;margin-bottom:6px}.telemetry-value[data-v-39c5aabc]{color:#91caff;font-size:24px;font-weight:600;line-height:1.2}.telemetry-sub[data-v-39c5aabc]{color:var(--text-secondary);font-size:11px;margin-top:4px}.telemetry-section[data-v-39c5aabc]{background:var(--bg-base);border:1px solid var(--border-color);border-radius:8px;padding:14px;min-height:140px}.telemetry-section-title[data-v-39c5aabc]{color:var(--text-secondary);font-size:12px;margin-bottom:10px}.telemetry-list[data-v-39c5aabc]{display:flex;flex-direction:column;gap:8px}.telemetry-row[data-v-39c5aabc]{display:flex;justify-content:space-between;gap:12px;color:var(--text-secondary);font-size:12px}.telemetry-empty[data-v-39c5aabc]{color:var(--text-muted);font-size:12px}
|