enigma-memory 0.1.18 → 0.1.22

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.
Files changed (276) hide show
  1. package/README.md +76 -24
  2. package/apps/cli/bin/enigma-desktop.mjs +140 -0
  3. package/apps/cli/bin/enigma-terminal.mjs +78 -0
  4. package/apps/cli/bin/enigma.mjs +1923 -285
  5. package/apps/desktop/electron-main.cjs +217 -0
  6. package/apps/desktop/package.json +12 -0
  7. package/apps/desktop/src/app.js +264 -7
  8. package/apps/desktop/src/index.html +3514 -1373
  9. package/apps/desktop/src/launch-electron.mjs +51 -0
  10. package/apps/desktop/src/server.mjs +2914 -0
  11. package/apps/desktop/src/styles.css +2972 -260
  12. package/apps/desktop/src/zk-browser-prove.mjs +53 -0
  13. package/apps/desktop/src/zk-state.mjs +1789 -0
  14. package/apps/gateway/bin/enigma-gateway.mjs +102 -5
  15. package/apps/gateway/src/server.mjs +271 -8
  16. package/apps/ios/EnigmaCore/Package.swift +12 -0
  17. package/apps/ios/EnigmaCore/Sources/EnigmaCore/EnigmaAPIClient.swift +227 -0
  18. package/apps/ios/EnigmaCore/Sources/EnigmaCore/Models.swift +278 -0
  19. package/apps/ios/EnigmaCore/Sources/EnigmaCore/PKCE.swift +96 -0
  20. package/apps/ios/EnigmaCore/Sources/EnigmaCore/PrivacyMinimizer.swift +187 -0
  21. package/apps/ios/EnigmaCore/Sources/EnigmaCore/ToolModels.swift +129 -0
  22. package/apps/ios/EnigmaCore/Tests/EnigmaCoreTests/EnigmaCoreTests.swift +42 -0
  23. package/apps/ios/EnigmaIOS/Enigma/AppModel.swift +346 -0
  24. package/apps/ios/EnigmaIOS/Enigma/Assets.xcassets/AccentColor.colorset/Contents.json +12 -0
  25. package/apps/ios/EnigmaIOS/Enigma/Assets.xcassets/AppIcon.appiconset/Contents.json +11 -0
  26. package/apps/ios/EnigmaIOS/Enigma/Assets.xcassets/AppIcon.appiconset/EnigmaAppIcon.png +0 -0
  27. package/apps/ios/EnigmaIOS/Enigma/Assets.xcassets/Contents.json +3 -0
  28. package/apps/ios/EnigmaIOS/Enigma/Assets.xcassets/LaunchBackground.colorset/Contents.json +12 -0
  29. package/apps/ios/EnigmaIOS/Enigma/ChatView.swift +181 -0
  30. package/apps/ios/EnigmaIOS/Enigma/CouncilView.swift +78 -0
  31. package/apps/ios/EnigmaIOS/Enigma/CreateView.swift +152 -0
  32. package/apps/ios/EnigmaIOS/Enigma/EnigmaApp.swift +52 -0
  33. package/apps/ios/EnigmaIOS/Enigma/Info.plist +52 -0
  34. package/apps/ios/EnigmaIOS/Enigma/NaturalLanguagePrivacyTagger.swift +26 -0
  35. package/apps/ios/EnigmaIOS/Enigma/OAuthClient.swift +321 -0
  36. package/apps/ios/EnigmaIOS/Enigma/OnboardingView.swift +105 -0
  37. package/apps/ios/EnigmaIOS/Enigma/PrivateVaultView.swift +275 -0
  38. package/apps/ios/EnigmaIOS/Enigma/SecureStore.swift +76 -0
  39. package/apps/ios/EnigmaIOS/Enigma/SettingsView.swift +60 -0
  40. package/apps/ios/EnigmaIOS/Enigma/Theme.swift +80 -0
  41. package/apps/ios/EnigmaIOS/EnigmaIOS.xcodeproj/project.pbxproj +211 -0
  42. package/apps/ios/EnigmaIOS/EnigmaIOS.xcodeproj/xcshareddata/xcschemes/Enigma.xcscheme +23 -0
  43. package/apps/native-host/README.md +19 -8
  44. package/apps/native-host/bin/enigma-native-host.mjs +229 -13
  45. package/apps/relay/bin/enigma-relay.mjs +103 -5
  46. package/apps/relay/src/federation-runtime.mjs +618 -0
  47. package/apps/relay/src/server.mjs +310 -9
  48. package/apps/verifier/bin/enigma-verify.mjs +327 -11
  49. package/cortex-v3/circuits/build/intent_vk_bytes.json +35 -0
  50. package/cortex-v3/circuits/build/sale_vk_bytes.json +35 -0
  51. package/cortex-v3/circuits/build/vk_bytes.json +32 -0
  52. package/cortex-v3/proving-assets.json +64 -0
  53. package/cortex-v3/zk/BUILD-CONTRACT.md +87 -0
  54. package/cortex-v3/zk/action-transition-vk.json +119 -0
  55. package/cortex-v3/zk/alias-adversarial.test.mjs +220 -0
  56. package/cortex-v3/zk/groth16-verify-child.mjs +17 -0
  57. package/cortex-v3/zk/intent-witness.mjs +365 -0
  58. package/cortex-v3/zk/intent-witness.test.mjs +485 -0
  59. package/cortex-v3/zk/proving-assets.mjs +203 -0
  60. package/cortex-v3/zk/sale-witness.mjs +783 -0
  61. package/cortex-v3/zk/sale-witness.test.mjs +784 -0
  62. package/cortex-v3/zk/sealed-sale-release-vk.json +119 -0
  63. package/cortex-v3/zk/settlement-evidence.mjs +722 -0
  64. package/cortex-v3/zk/setup-intent.mjs +688 -0
  65. package/cortex-v3/zk/setup-sale.mjs +666 -0
  66. package/cortex-v3/zk/setup.mjs +594 -0
  67. package/cortex-v3/zk/witness.mjs +184 -0
  68. package/cortex-v3/zk/zk-codec.mjs +232 -0
  69. package/cortex-v3/zk/zk-codec.test.mjs +293 -0
  70. package/cortex-v3/zk/zk-settle.mjs +370 -0
  71. package/cortex-v3/zk/zk-tree.mjs +256 -0
  72. package/cortex-v3/zk/zk-tree.test.mjs +419 -0
  73. package/deploy/docker-compose.local-production-simulation.yml +36 -0
  74. package/docs/browser-extension-install.md +8 -6
  75. package/docs/client-connectors.md +15 -11
  76. package/docs/developer-ecosystem.md +15 -13
  77. package/docs/enigma-memory-ready-conformance.md +11 -9
  78. package/docs/install-anywhere.md +61 -28
  79. package/docs/installers-and-desktop.md +8 -7
  80. package/docs/novelty-invention-candidates.md +161 -161
  81. package/docs/proof-network-claim-boundaries.md +320 -318
  82. package/examples/01-quickstart-agent/index.mjs +49 -0
  83. package/examples/01_agent_memory_quickstart.mjs +57 -0
  84. package/examples/02-multi-agent-swarm/index.mjs +57 -0
  85. package/examples/02_cross_model_passport.mjs +64 -0
  86. package/examples/03-langchain-memory/index.mjs +41 -0
  87. package/examples/03_poseidon_commitment_verification.mjs +71 -0
  88. package/examples/04-python-trading-agent/trader.py +49 -0
  89. package/examples/README.md +27 -0
  90. package/examples/ci/github-actions.yml +7 -2
  91. package/package.json +142 -11
  92. package/packages/adapters/PACKAGE_CONTRACT.md +1 -1
  93. package/packages/connectors/src/index.js +196 -4
  94. package/packages/connectors/swarm-router.mjs +168 -0
  95. package/packages/core/src/index.js +248 -1
  96. package/packages/core/src/version.mjs +7 -0
  97. package/packages/dev-tools/package.json +19 -0
  98. package/packages/dev-tools/src/index.js +4 -0
  99. package/packages/dev-tools/src/memory-benchmark-suite.js +112 -0
  100. package/packages/dev-tools/src/swarm-simulator.js +101 -0
  101. package/packages/dev-tools/src/vault-inspector.js +114 -0
  102. package/packages/dev-tools/src/vector-benchmark.js +100 -0
  103. package/packages/developer-platform/src/access-credentials.js +341 -0
  104. package/packages/developer-platform/src/http.js +132 -0
  105. package/packages/developer-platform/src/index.js +4 -0
  106. package/packages/developer-platform/src/usage-http.js +60 -0
  107. package/packages/developer-platform/src/usage.js +295 -0
  108. package/packages/enclave-runtime/attestation.mjs +159 -0
  109. package/packages/enclave-runtime/index.mjs +47 -0
  110. package/packages/enclave-runtime/session-manager.mjs +253 -0
  111. package/packages/enclave-runtime/zeroization-proof.mjs +227 -0
  112. package/packages/enigma-reflex/package.json +14 -0
  113. package/packages/enigma-reflex/src/index.js +204 -0
  114. package/packages/enigma-reflex/training/generate-dataset.mjs +40 -0
  115. package/packages/enigma-reflex/training/requirements.txt +8 -0
  116. package/packages/enigma-reflex/training/train.py +314 -0
  117. package/packages/enigma-weave/LICENSE +22 -0
  118. package/packages/enigma-weave/UPSTREAM.json +21 -0
  119. package/packages/enigma-weave/package.json +14 -0
  120. package/packages/enigma-weave/src/index.js +286 -0
  121. package/packages/hosted-cloud/src/index.js +80 -5
  122. package/packages/importers/src/index.js +432 -0
  123. package/packages/inference-runtime/src/browser.js +401 -0
  124. package/packages/inference-runtime/src/chat.js +265 -0
  125. package/packages/inference-runtime/src/code.js +407 -0
  126. package/packages/inference-runtime/src/contracts.js +162 -0
  127. package/packages/inference-runtime/src/http.js +232 -0
  128. package/packages/inference-runtime/src/image.js +186 -0
  129. package/packages/inference-runtime/src/index.js +10 -0
  130. package/packages/inference-runtime/src/model-router.js +320 -0
  131. package/packages/inference-runtime/src/platform.js +125 -0
  132. package/packages/inference-runtime/src/privacy.js +400 -0
  133. package/packages/inference-runtime/src/video.js +253 -0
  134. package/packages/mcp-server/README.md +22 -6
  135. package/packages/mcp-server/bin/enigma-mcp.mjs +2 -1
  136. package/packages/mcp-server/src/index.js +1418 -105
  137. package/packages/mcp-server/src/oauth.js +561 -0
  138. package/packages/mcp-server/src/private-handoff.js +84 -0
  139. package/packages/mcp-server/src/remote-http.js +273 -0
  140. package/packages/mcp-server/src/remote-policy.js +72 -0
  141. package/packages/mcp-server/swarm-bridge.mjs +361 -0
  142. package/packages/mesh/index.d.ts +283 -0
  143. package/packages/mesh/package.json +23 -0
  144. package/packages/mesh/src/crypto.js +189 -0
  145. package/packages/mesh/src/federation-packets.js +353 -0
  146. package/packages/mesh/src/gossip.js +311 -0
  147. package/packages/mesh/src/index.js +6 -0
  148. package/packages/mesh/src/protocol.js +255 -0
  149. package/packages/mesh/src/router.js +279 -0
  150. package/packages/mesh/src/transport.js +306 -0
  151. package/packages/passport/src/index.js +426 -1
  152. package/packages/private-economy/src/credits-http.js +100 -0
  153. package/packages/private-economy/src/credits.js +447 -0
  154. package/packages/private-economy/src/index.js +5 -0
  155. package/packages/private-economy/src/payments-http.js +120 -0
  156. package/packages/private-economy/src/payments.js +509 -0
  157. package/packages/private-economy/src/x402.js +346 -0
  158. package/packages/proof-network/PACKAGE_CONTRACT.md +21 -0
  159. package/packages/rag/index.d.ts +182 -0
  160. package/packages/rag/models/Xenova/all-MiniLM-L6-v2/THIRD_PARTY_LICENSES.txt +207 -0
  161. package/packages/rag/models/Xenova/all-MiniLM-L6-v2/config.json +25 -0
  162. package/packages/rag/models/Xenova/all-MiniLM-L6-v2/onnx/model_quantized.onnx +0 -0
  163. package/packages/rag/models/Xenova/all-MiniLM-L6-v2/sha256-manifest.json +28 -0
  164. package/packages/rag/models/Xenova/all-MiniLM-L6-v2/tokenizer.json +30686 -0
  165. package/packages/rag/models/Xenova/all-MiniLM-L6-v2/tokenizer_config.json +15 -0
  166. package/packages/rag/package.json +27 -0
  167. package/packages/rag/src/blinded-search.js +109 -0
  168. package/packages/rag/src/bm25.js +169 -0
  169. package/packages/rag/src/embeddings.js +459 -0
  170. package/packages/rag/src/hybrid.js +76 -0
  171. package/packages/rag/src/index.js +38 -0
  172. package/packages/rag/src/reranker.js +61 -0
  173. package/packages/rag/src/research.js +107 -0
  174. package/packages/rag/src/vector-store.js +430 -0
  175. package/packages/rag/src/verify-model-artifacts.mjs +4 -0
  176. package/packages/sdk/index.d.ts +760 -0
  177. package/packages/sdk/package.json +33 -0
  178. package/packages/sdk/python/README.md +24 -0
  179. package/packages/sdk/python/enigma_sdk.py +250 -0
  180. package/packages/sdk/python/pyproject.toml +34 -0
  181. package/packages/sdk/python/requirements.txt +1 -0
  182. package/packages/sdk/python/setup.py +20 -0
  183. package/packages/sdk/src/federation/capability-grant.js +389 -0
  184. package/packages/sdk/src/federation/federation-router.js +360 -0
  185. package/packages/sdk/src/federation/ghostmesh-bridge.js +497 -0
  186. package/packages/sdk/src/federation/index.js +3 -0
  187. package/packages/sdk/src/index.js +1796 -0
  188. package/packages/sdk/src/intelligence/contradiction.js +337 -0
  189. package/packages/sdk/src/intelligence/decision-engine.js +155 -0
  190. package/packages/sdk/src/intelligence/index.js +4 -0
  191. package/packages/sdk/src/intelligence/ontology.js +122 -0
  192. package/packages/sdk/src/intelligence/temporal.js +123 -0
  193. package/packages/sdk/src/market-client.js +142 -0
  194. package/packages/sdk/src/mesh-client.js +110 -0
  195. package/packages/sdk/src/middleware/index.js +3 -0
  196. package/packages/sdk/src/middleware/langchain.js +159 -0
  197. package/packages/sdk/src/middleware/llamaindex.js +101 -0
  198. package/packages/sdk/src/middleware/vercel-ai.js +112 -0
  199. package/packages/sdk/src/rag-client.js +85 -0
  200. package/packages/sdk/src/swarm-orchestrator.js +260 -0
  201. package/packages/settlement/PACKAGE_CONTRACT.md +1 -1
  202. package/packages/snapcompact/THIRD_PARTY_LICENSES.txt +40 -0
  203. package/packages/snapcompact/assets/8x13-latin1.bdf +3837 -0
  204. package/packages/snapcompact/index.d.ts +284 -0
  205. package/packages/snapcompact/package.json +25 -0
  206. package/packages/snapcompact/src/index.js +716 -0
  207. package/packages/storage/PACKAGE_CONTRACT.md +1 -1
  208. package/packages/terminal-console/animations.mjs +240 -0
  209. package/packages/terminal-console/auto-anchor.mjs +220 -0
  210. package/packages/terminal-console/banner.mjs +91 -0
  211. package/packages/terminal-console/commands.mjs +459 -0
  212. package/packages/terminal-console/delegation.mjs +152 -0
  213. package/packages/terminal-console/index.mjs +5 -0
  214. package/packages/terminal-console/outbox.mjs +143 -0
  215. package/packages/terminal-console/phantom-bridge.mjs +637 -0
  216. package/packages/terminal-console/repl.mjs +136 -0
  217. package/packages/terminal-console/signer-store.mjs +130 -0
  218. package/packages/terminal-console/solana-rpc.mjs +214 -0
  219. package/packages/terminal-console/solana-transport.mjs +189 -0
  220. package/packages/terminal-tui/dashboard.mjs +214 -0
  221. package/packages/terminal-tui/index.mjs +28 -0
  222. package/packages/terminal-tui/merkle-tree-renderer.mjs +268 -0
  223. package/packages/terminal-tui/telemetry-hud.mjs +137 -0
  224. package/packages/vault/index.d.ts +449 -0
  225. package/packages/vault/package.json +27 -0
  226. package/packages/vault/src/e2ee.mjs +393 -0
  227. package/packages/vault/src/enclave.js +481 -0
  228. package/packages/vault/src/erasure.js +207 -0
  229. package/packages/vault/src/index.js +1018 -155
  230. package/packages/vault/src/persistence.js +307 -0
  231. package/packages/vault/src/poseidon.js +354 -0
  232. package/packages/vault/src/receipt.js +459 -0
  233. package/scripts/benchmark-optical-context.mjs +166 -0
  234. package/scripts/bootstrap-enigma.mjs +502 -0
  235. package/scripts/build-edge-backend-workers.mjs +20 -5
  236. package/scripts/build-goal-completion-audit.mjs +72 -25
  237. package/scripts/build-hosted-api-key-lifecycle.mjs +26 -8
  238. package/scripts/build-hosted-customer-lifecycle.mjs +20 -3
  239. package/scripts/build-hosted-probe-worker.mjs +19 -4
  240. package/scripts/build-installer-assets.mjs +41 -21
  241. package/scripts/build-operator-evidence-starter.mjs +59 -1
  242. package/scripts/build-production-backend-env-kit.mjs +2 -0
  243. package/scripts/build-production-unblocker.mjs +3 -0
  244. package/scripts/check.mjs +17 -3
  245. package/scripts/collect-hosted-backend-live-evidence.mjs +49 -12
  246. package/scripts/install-enigma-local.mjs +18 -5
  247. package/scripts/release-audit.mjs +65 -109
  248. package/scripts/release-provenance.mjs +6 -0
  249. package/scripts/run-backend-readiness-smoke.mjs +112 -10
  250. package/scripts/scan-secrets.mjs +1 -0
  251. package/scripts/simulate-production-env.mjs +7 -2
  252. package/scripts/validate-hosted-backend-live.mjs +112 -1
  253. package/specs/antibody-pack-v1.schema.json +95 -0
  254. package/specs/antigen-envelope-v1.schema.json +81 -0
  255. package/specs/boundary-manifest-v1.schema.json +35 -35
  256. package/specs/capsule-v1.schema.json +55 -55
  257. package/specs/claim-boundary-manifest-v1.schema.json +22 -22
  258. package/specs/claim-ledger-v1.schema.json +291 -0
  259. package/specs/context-passport-v1.schema.json +59 -0
  260. package/specs/deletion-tombstone-v1.schema.json +26 -26
  261. package/specs/evidence-packet-v1.schema.json +177 -0
  262. package/specs/hosted-backend-live-evidence-v1.schema.json +72 -3
  263. package/specs/immune-scan-report-v1.schema.json +112 -0
  264. package/specs/lifecycle-receipt-log-v1.schema.json +67 -0
  265. package/specs/memory-atom-v1.schema.json +59 -0
  266. package/specs/memory-event-v1.schema.json +42 -42
  267. package/specs/passport-v1.schema.json +50 -50
  268. package/specs/proof-of-non-use-v1.schema.json +65 -0
  269. package/specs/quarantine-record-v1.schema.json +126 -0
  270. package/specs/receipt-v1.schema.json +61 -61
  271. package/specs/state-checkpoint-v1.schema.json +37 -37
  272. package/specs/trust-bundle-v1.schema.json +56 -56
  273. package/specs/trust-card-v1.schema.json +119 -0
  274. package/docs/proof-network-launch-plan.md +0 -421
  275. package/packages/metering/PACKAGE_CONTRACT.md +0 -20
  276. package/scripts/build-ai-orchestration-plan.mjs +0 -248
@@ -1,13 +1,24 @@
1
1
  #!/usr/bin/env node
2
+ import { fork } from 'node:child_process';
3
+ import { createHash } from 'node:crypto';
4
+ import { createRequire } from 'node:module';
2
5
  import { realpathSync } from 'node:fs';
3
6
  import { readFile } from 'node:fs/promises';
4
- import { pathToFileURL } from 'node:url';
7
+ import { fileURLToPath, pathToFileURL } from 'node:url';
5
8
  import {
6
9
  verifyReceipt,
7
10
  verifyReceiptChain,
8
11
  verifyCheckpoint,
9
12
  } from '../../../packages/core/src/index.js';
10
-
13
+ import { verifyMemoryReceipt } from '../../../packages/vault/src/receipt.js';
14
+ import {
15
+ ZK_SETTLEMENT_EVIDENCE_SCHEMA,
16
+ ZK_VERIFICATION_KEY_PINS,
17
+ proofToSnarkjs,
18
+ validateZkSettlementEvidence,
19
+ validateZkSettlementEvidenceGraph,
20
+ verifyZkSettlementEvidence,
21
+ } from '../../../cortex-v3/zk/settlement-evidence.mjs';
11
22
  function json(value) {
12
23
  return JSON.stringify(value, null, 2);
13
24
  }
@@ -123,12 +134,184 @@ function compareCommittedSequence(receipts, committed, errors) {
123
134
  }));
124
135
  }
125
136
  }
137
+ function zkReceiptsFromBundle(bundle) {
138
+ return asArray(
139
+ bundle?.zk_receipts
140
+ ?? bundle?.zkSettlementReceipts
141
+ ?? bundle?.settlementReceipts
142
+ ?? (bundle?.settlementReceipt ? [bundle.settlementReceipt] : []),
143
+ );
144
+ }
145
+
146
+ // A bundle is an offline artifact, not a streaming proof service. Capping it at
147
+ // 64 receipts bounds CPU time, child-process lifetime, replay state, and parsed
148
+ // verification-key retention while remaining well above normal lifecycle size.
149
+ export const MAX_ZK_SETTLEMENT_RECEIPTS = 64;
150
+
151
+ const GROTH16_PROOF_EVENTS = new Set(['action.append', 'action.revoke', 'sale.list']);
152
+ const verificationKeyCache = new Map();
153
+ const MAX_VERIFICATION_KEY_CACHE_ITEMS = 16;
154
+ const GROTH16_WORKER_ARG = '--enigma-groth16-worker';
155
+ const IS_GROTH16_WORKER = process.argv[2] === GROTH16_WORKER_ARG;
156
+
157
+ function emitInstrumentation(options, event, details = {}) {
158
+ const callback = options?.instrumentation?.[event];
159
+ if (typeof callback === 'function') callback(details);
160
+ }
161
+
162
+ async function loadVerificationKey(circuit, expectedHash, options) {
163
+ const pin = ZK_VERIFICATION_KEY_PINS[circuit];
164
+ if (!pin) throw new Error(`no pinned verification key for circuit ${circuit}`);
165
+ const path = options.verificationKeyPaths?.[circuit] ?? pin.path;
166
+ const cacheKey = `${circuit}\0${String(path)}`;
167
+ let pending = verificationKeyCache.get(cacheKey);
168
+ if (!pending) {
169
+ pending = (async () => {
170
+ emitInstrumentation(options, 'verificationKeyLoad', { circuit, path: String(path) });
171
+ const raw = await readFile(path);
172
+ const actualHash = createHash('sha256').update(raw).digest('hex');
173
+ if (actualHash !== pin.sha256) {
174
+ throw new Error(`verification key hash mismatch for ${circuit}: expected sha256:${pin.sha256}, got sha256:${actualHash}`);
175
+ }
176
+ const key = JSON.parse(raw.toString('utf8'));
177
+ if (key.protocol !== 'groth16' || key.curve !== 'bn128' || key.nPublic !== 6) {
178
+ throw new Error(`pinned verification key for ${circuit} has an invalid Groth16 contract`);
179
+ }
180
+ return key;
181
+ })();
182
+ if (verificationKeyCache.size >= MAX_VERIFICATION_KEY_CACHE_ITEMS) {
183
+ verificationKeyCache.delete(verificationKeyCache.keys().next().value);
184
+ }
185
+ verificationKeyCache.set(cacheKey, pending);
186
+ pending.catch(() => {
187
+ if (verificationKeyCache.get(cacheKey) === pending) verificationKeyCache.delete(cacheKey);
188
+ });
189
+ }
190
+ const key = await pending;
191
+ if (expectedHash !== `sha256:${pin.sha256}`) {
192
+ throw new Error(`verification key pin mismatch for ${circuit}`);
193
+ }
194
+ return key;
195
+ }
196
+
197
+ class Groth16VerifierWorker {
198
+ constructor(options) {
199
+ this.options = options;
200
+ this.child = null;
201
+ this.pending = null;
202
+ this.nextRequestId = 1;
203
+ this.closed = false;
204
+ }
126
205
 
206
+ ensureChild() {
207
+ if (this.closed) throw new Error('Groth16 verifier worker is closed');
208
+ if (this.child) return;
209
+ const child = fork(fileURLToPath(import.meta.url), [GROTH16_WORKER_ARG], {
210
+ stdio: ['ignore', 'ignore', 'ignore', 'ipc'],
211
+ });
212
+ this.child = child;
213
+ emitInstrumentation(this.options, 'workerSpawn', {});
214
+ child.on('message', (message) => {
215
+ if (!this.pending || message?.id !== this.pending.id) return;
216
+ if (message.error) this.finishPending(new Error(message.error));
217
+ else this.finishPending(null, message.verified === true);
218
+ });
219
+ child.on('error', (error) => this.failChild(error));
220
+ child.on('exit', (code, signal) => {
221
+ if (this.child === child) this.child = null;
222
+ if (this.pending) {
223
+ this.finishPending(new Error(`snarkjs verifier child exited before returning a verdict (code ${code}, signal ${signal ?? 'none'})`));
224
+ }
225
+ });
226
+ }
227
+
228
+ finishPending(error, result) {
229
+ const pending = this.pending;
230
+ if (!pending) return;
231
+ this.pending = null;
232
+ clearTimeout(pending.timer);
233
+ if (error) pending.reject(error);
234
+ else pending.resolve(result);
235
+ }
236
+
237
+ failChild(error) {
238
+ const child = this.child;
239
+ this.child = null;
240
+ if (child && !child.killed) child.kill('SIGKILL');
241
+ this.finishPending(error);
242
+ }
243
+
244
+ async verify(request, timeoutMs) {
245
+ if (this.pending) throw new Error('Groth16 verifier worker received overlapping requests');
246
+ this.ensureChild();
247
+ const id = this.nextRequestId++;
248
+ emitInstrumentation(this.options, 'proofCheck', { circuit: request.circuit, receiptRef: request.receiptRef });
249
+ return await new Promise((resolve, reject) => {
250
+ const timer = setTimeout(() => {
251
+ const error = new Error(`snarkjs verification exceeded ${timeoutMs}ms`);
252
+ this.failChild(error);
253
+ }, timeoutMs);
254
+ this.pending = { id, timer, resolve, reject };
255
+ this.child.send({
256
+ id,
257
+ verificationKey: request.verificationKey,
258
+ publicSignals: request.publicSignals,
259
+ proof: request.proof,
260
+ }, (error) => {
261
+ if (error) this.failChild(error);
262
+ });
263
+ });
264
+ }
127
265
 
266
+ async close() {
267
+ this.closed = true;
268
+ const child = this.child;
269
+ this.child = null;
270
+ if (!child) return;
271
+ if (this.pending) this.finishPending(new Error('Groth16 verifier worker closed with a pending request'));
272
+ await new Promise((resolve) => {
273
+ let settled = false;
274
+ let forceTimer;
275
+ const finish = () => {
276
+ if (settled) return;
277
+ settled = true;
278
+ clearTimeout(forceTimer);
279
+ resolve();
280
+ };
281
+ forceTimer = setTimeout(() => {
282
+ try { child.kill('SIGKILL'); } catch {}
283
+ finish();
284
+ }, 1_000);
285
+ child.once('exit', finish);
286
+ child.kill();
287
+ });
288
+ }
289
+ }
128
290
 
291
+ function startGroth16Worker() {
292
+ const require = createRequire(import.meta.url);
293
+ const snarkjs = require('snarkjs');
294
+ let queue = Promise.resolve();
295
+ process.on('message', (request) => {
296
+ queue = queue.then(async () => {
297
+ try {
298
+ const verified = await snarkjs.groth16.verify(
299
+ request.verificationKey,
300
+ request.publicSignals,
301
+ request.proof,
302
+ );
303
+ process.send?.({ id: request.id, verified });
304
+ } catch (error) {
305
+ process.send?.({ id: request.id, error: error.message });
306
+ }
307
+ });
308
+ });
309
+ process.once('disconnect', () => process.exit(0));
310
+ }
129
311
 
130
- export function verifyBundle(bundle) {
312
+ export function verifyBundle(bundle, options = {}) {
131
313
  const receipts = asArray(bundle?.receipts);
314
+ const zkReceipts = zkReceiptsFromBundle(bundle);
132
315
  const checkpoints = asArray(bundle?.checkpoints ?? bundle?.passport?.checkpoints);
133
316
  const publicKey = publicKeyFromBundle(bundle);
134
317
  const errors = [];
@@ -138,10 +321,10 @@ export function verifyBundle(bundle) {
138
321
  if (!bundle || typeof bundle !== 'object') {
139
322
  return { ok: false, errors: [makeError('BUNDLE_INVALID', 'Bundle must be a JSON object.')] };
140
323
  }
141
- if (receipts.length === 0) {
142
- errors.push(makeError('RECEIPTS_MISSING', 'Bundle does not contain receipts.'));
324
+ if (receipts.length === 0 && zkReceipts.length === 0) {
325
+ errors.push(makeError('RECEIPTS_MISSING', 'Bundle does not contain memory or ZK settlement receipts.'));
143
326
  }
144
- if (!publicKey) {
327
+ if (receipts.length > 0 && !publicKey) {
145
328
  errors.push(makeError('PUBLIC_KEY_MISSING', 'Bundle does not contain an offline verifier public key.'));
146
329
  }
147
330
 
@@ -172,8 +355,14 @@ export function verifyBundle(bundle) {
172
355
  }
173
356
  }
174
357
 
175
- compareCommittedSequence(receipts, committed, errors);
358
+ if (zkReceipts.length > 0 && options.skipZk !== true) {
359
+ errors.push(makeError(
360
+ 'ZK_ASYNC_VERIFICATION_REQUIRED',
361
+ 'ZK settlement receipts require verifyBundleWithZk() or the enigma-verify CLI so snarkjs can verify Groth16 proofs.',
362
+ ));
363
+ }
176
364
 
365
+ compareCommittedSequence(receipts, committed, errors);
177
366
  if (receipts.length > 0 && checkpoints.length > 0 && publicKey) {
178
367
  const lastReceipt = receipts.at(-1);
179
368
  const lastCheckpoint = checkpoints.at(-1);
@@ -202,6 +391,84 @@ export function verifyBundle(bundle) {
202
391
  checked_at: new Date().toISOString(),
203
392
  receipt_count: receipts.length,
204
393
  checkpoint_count: checkpoints.length,
394
+ zk_receipt_count: zkReceipts.length,
395
+ errors,
396
+ };
397
+ }
398
+
399
+ export async function verifyBundleWithZk(bundle, options = {}) {
400
+ const report = verifyBundle(bundle, { skipZk: true });
401
+ const receipts = zkReceiptsFromBundle(bundle);
402
+ const errors = [...report.errors];
403
+ const hasProofBearingReceipts = receipts.some((receipt) => GROTH16_PROOF_EVENTS.has(receipt?.event));
404
+ if (receipts.length > MAX_ZK_SETTLEMENT_RECEIPTS) {
405
+ errors.push(makeError(
406
+ 'ZK_SETTLEMENT_RECEIPT_LIMIT',
407
+ `Bundle contains ${receipts.length} ZK settlement receipts; the safe maximum is ${MAX_ZK_SETTLEMENT_RECEIPTS}.`,
408
+ ));
409
+ return { ...report, ok: false, proof_valid: null, settlement_verified: false, errors };
410
+ }
411
+
412
+ const graphVerdict = validateZkSettlementEvidenceGraph(receipts);
413
+ if (!graphVerdict.ok) errors.push(...graphVerdict.errors.map((error) => verifierError(
414
+ error,
415
+ 'ZK_SETTLEMENT_GRAPH_INVALID',
416
+ 'ZK settlement receipt graph did not verify.',
417
+ )));
418
+
419
+ for (const receipt of receipts) {
420
+ const verdict = validateZkSettlementEvidence(receipt, options);
421
+ if (!verdict.ok) {
422
+ errors.push(...verdict.errors.map((error) => verifierError(
423
+ error,
424
+ 'ZK_SETTLEMENT_EVIDENCE_INVALID',
425
+ `ZK settlement receipt ${receipt?.receipt_ref ?? '<unknown>'} did not verify.`,
426
+ )));
427
+ }
428
+ }
429
+
430
+ // No Groth16 work is launched unless every cheap bundle, trust, signature,
431
+ // state-transition, lineage, transaction, and replay check has succeeded.
432
+ if (errors.length > 0) {
433
+ return { ...report, ok: false, proof_valid: null, settlement_verified: false, errors };
434
+ }
435
+
436
+ const worker = new Groth16VerifierWorker(options);
437
+ const timeoutMs = Number.isSafeInteger(options.groth16TimeoutMs) && options.groth16TimeoutMs > 0
438
+ ? options.groth16TimeoutMs
439
+ : 30_000;
440
+ try {
441
+ for (const receipt of receipts) {
442
+ if (!GROTH16_PROOF_EVENTS.has(receipt.event)) continue;
443
+ try {
444
+ const verificationKey = await loadVerificationKey(
445
+ receipt.circuit,
446
+ receipt.proof.verification_key?.sha256,
447
+ options,
448
+ );
449
+ const verified = await worker.verify({
450
+ circuit: receipt.circuit,
451
+ receiptRef: receipt.receipt_ref,
452
+ verificationKey,
453
+ publicSignals: receipt.proof.public_inputs.map((value) => BigInt(`0x${value}`).toString(10)),
454
+ proof: proofToSnarkjs(receipt.proof),
455
+ }, timeoutMs);
456
+ if (!verified) {
457
+ errors.push(makeError('ZK_EVIDENCE_GROTH16_INVALID', 'snarkjs rejected the Groth16 proof against the pinned verification key.'));
458
+ }
459
+ } catch (error) {
460
+ errors.push(makeError('ZK_EVIDENCE_GROTH16_INVALID', `Offline Groth16 verification failed closed: ${error.message}`));
461
+ }
462
+ }
463
+ } finally {
464
+ await worker.close();
465
+ }
466
+ const ok = errors.length === 0;
467
+ return {
468
+ ...report,
469
+ ok,
470
+ proof_valid: hasProofBearingReceipts ? ok : null,
471
+ settlement_verified: ok,
205
472
  errors,
206
473
  };
207
474
  }
@@ -210,14 +477,61 @@ export async function readBundle(path) {
210
477
  return JSON.parse(await readFile(path, 'utf8'));
211
478
  }
212
479
 
480
+ function optionValue(argv, name) {
481
+ const index = argv.indexOf(name);
482
+ return index >= 0 ? argv[index + 1] : null;
483
+ }
484
+
485
+ async function loadZkTrustOptions(argv) {
486
+ const trustPath = optionValue(argv, '--trust');
487
+ if (!trustPath) {
488
+ throw new Error('ZK settlement verification requires --trust <trust-registry.json>.');
489
+ }
490
+ const trust = await readBundle(trustPath);
491
+ if (
492
+ !trust
493
+ || !Array.isArray(trust.trusted_signers)
494
+ || trust.trusted_signers.length === 0
495
+ || typeof trust.program_id !== 'string'
496
+ || !trust.program_id
497
+ || typeof trust.cluster !== 'string'
498
+ || !trust.cluster
499
+ || !Array.isArray(trust.finalized_checkpoints)
500
+ || trust.finalized_checkpoints.length === 0
501
+ ) {
502
+ throw new Error('trust registry must contain non-empty trusted_signers, program_id, cluster, and finalized_checkpoints');
503
+ }
504
+ return {
505
+ trustedSigners: trust.trusted_signers,
506
+ expectedProgramId: trust.program_id,
507
+ expectedCluster: trust.cluster,
508
+ finalizedCheckpoints: trust.finalized_checkpoints,
509
+ };
510
+ }
511
+
213
512
  export async function main(argv = process.argv.slice(2), io = { stdout: process.stdout, stderr: process.stderr }) {
214
- const file = argv.find((arg) => !arg.startsWith('-'));
513
+ const file = argv.find((arg, index) => !arg.startsWith('-') && argv[index - 1] !== '--trust');
215
514
  if (!file || argv.includes('--help') || argv.includes('-h')) {
216
- io.stdout.write(`${json({ usage: 'enigma-verify <exported-bundle.json>', output: 'JSON verification report' })}\n`);
515
+ io.stdout.write(`${json({ usage: 'enigma-verify <bundle-or-receipt.json> [--trust zk-trust-registry.json]', zk_trust_registry: { trusted_signers: ['base64-public-key or key-id'], program_id: 'expected program', cluster: 'expected cluster', finalized_checkpoints: ['receipt-bound finalized checkpoint objects'] }, output: 'JSON verification report' })}\n`);
217
516
  return 0;
218
517
  }
219
518
  try {
220
- const report = verifyBundle(await readBundle(file));
519
+ const data = await readBundle(file);
520
+ if (data?.schema === ZK_SETTLEMENT_EVIDENCE_SCHEMA) {
521
+ const trustOptions = await loadZkTrustOptions(argv);
522
+ const report = await verifyZkSettlementEvidence(data, { ...trustOptions, seenRefs: new Set() });
523
+ io.stdout.write(`${json({ ...report, schema: 'enigma.zk_settlement_verification_report.v1' })}\n`);
524
+ return report.ok ? 0 : 1;
525
+ }
526
+ if (data && (data.schema === 'enigma.memory_receipt.v2' || (data.commitment && data.agent_pubkey && data.signature))) {
527
+ const report = verifyMemoryReceipt(data);
528
+ io.stdout.write(`${json({ ok: report.ok, verified: report.verified, schema: 'enigma.receipt_verification_report.v2', report })}\n`);
529
+ return report.ok ? 0 : 1;
530
+ }
531
+ const hasZkReceipts = zkReceiptsFromBundle(data).length > 0;
532
+ const report = hasZkReceipts
533
+ ? await verifyBundleWithZk(data, await loadZkTrustOptions(argv))
534
+ : verifyBundle(data);
221
535
  io.stdout.write(`${json(report)}\n`);
222
536
  return report.ok ? 0 : 1;
223
537
  } catch (error) {
@@ -235,6 +549,8 @@ function isMainModule(metaUrl) {
235
549
  }
236
550
 
237
551
 
238
- if (isMainModule(import.meta.url)) {
552
+ if (IS_GROTH16_WORKER) {
553
+ startGroth16Worker();
554
+ } else if (isMainModule(import.meta.url)) {
239
555
  process.exitCode = await main();
240
556
  }
@@ -0,0 +1,35 @@
1
+ {
2
+ "format": "raw-be-hex-v1",
3
+ "curve": "bn128",
4
+ "g2LimbOrder": "c1c0",
5
+ "proofNote": "pi_a is raw — the on-chain program negates A",
6
+ "circuit": "intent_attestation",
7
+ "circuitVersion": 2,
8
+ "numPublicInputs": 4,
9
+ "icCount": 5,
10
+ "icPaddedTo": 7,
11
+ "alphaG1": "2d4d9aa7e302d9df41749d5507949d05dbea33fbb16c643b22f599a2be6df2e214bedd503c37ceb061d8ec60209fe345ce89830a19230301f076caff004d1926",
12
+ "betaG2": "0967032fcbf776d1afc985f88877f182d38480a653f2decaa9794cbc3bf3060c0e187847ad4c798374d0d6732bf501847dd68bc0e071241e0213bc7fc13db7ab304cfbd1e08a704a99f5e847d93f8c3caafddec46b7a0d379da69a4d112346a71739c1b1a457a8c7313123d24d2f9192f896b7c63eea05a9d57f06547ad0cec8",
13
+ "gammaG2": "198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa",
14
+ "deltaG2": "2c80382a4d2011a8047aa6712fb7998f63aaac9d904fe46fda37c705453f5d55011153e8b44da8dea7ff23cfc54402bd8dda85b6fd5b6e8c311ac04a24be81961ec087bc02f5a629cdad62683f7fd085693d8d9efd4331f680454072b55e3c120ed38191e3494aff5760cbb6f6a69296dcdbfca684dabc15f877e3dba3d92e46",
15
+ "ic": [
16
+ "24f95d74e34ded414c3e53f386722cf7635e3cb9dc3120b3bbc8110608b11d35283eed3710f3680588265308925d58ac23935f90f1448de5d2c76d8b7812778f",
17
+ "0daa93c2b8773b1b45a73d1032cecbc39dd38b4b726f0e6816f0cdc9eb64b59a277174ab8f322ece1e035389d0f486880ca9d656e087eb1b946582691e42b138",
18
+ "0d6d39d085f4470bdb472f8c2abcdfc8de0520b1f9a5632f3dd504e93f6fe9ee1a19eb6ed785a5fb2236d89c260be061a84645fe1eab6cc958d78d1ba63706e4",
19
+ "1f91d72d148fcd918eb093681b0b62ddb8afa8763fd99e97c208c22650c703c7202a4f5cee6f9a2e0103c08eb21cf7f49568de0f4b4c004efe763dfa8de2130f",
20
+ "2a37257d7820013d370539ad680c98346801a569015c545c61a818e8cd77326620723e84dc1c6a34d830001605339f25993e7990e41ad2b0219cc67dc70f4509",
21
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
22
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
23
+ ],
24
+ "ceremony": "development single-party",
25
+ "ceremonyDetail": {
26
+ "ptau": "reused repo-local file (no download)",
27
+ "ptauBytes": 302072984,
28
+ "ptauPower": 18,
29
+ "r1csSha256": "c485c9bb702d9db158ffeffa023ca24dd425764cdc876fadfbc63da5d8efef5d",
30
+ "constraintCount": 22702,
31
+ "contribution": "enigma-intent-dev-1 (random entropy) + random beacon (10 iterations)"
32
+ },
33
+ "source": "intent_verification_key.json",
34
+ "createdAt": "2026-08-23T07:05:55.037Z"
35
+ }
@@ -0,0 +1,35 @@
1
+ {
2
+ "format": "raw-be-hex-v1",
3
+ "curve": "bn128",
4
+ "g2LimbOrder": "c1c0",
5
+ "proofNote": "pi_a is raw — the on-chain program negates A",
6
+ "circuit": "sealed_sale_release",
7
+ "circuitVersion": 3,
8
+ "numPublicInputs": 6,
9
+ "icCount": 7,
10
+ "icPaddedTo": 7,
11
+ "alphaG1": "2d4d9aa7e302d9df41749d5507949d05dbea33fbb16c643b22f599a2be6df2e214bedd503c37ceb061d8ec60209fe345ce89830a19230301f076caff004d1926",
12
+ "betaG2": "0967032fcbf776d1afc985f88877f182d38480a653f2decaa9794cbc3bf3060c0e187847ad4c798374d0d6732bf501847dd68bc0e071241e0213bc7fc13db7ab304cfbd1e08a704a99f5e847d93f8c3caafddec46b7a0d379da69a4d112346a71739c1b1a457a8c7313123d24d2f9192f896b7c63eea05a9d57f06547ad0cec8",
13
+ "gammaG2": "198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa",
14
+ "deltaG2": "01cfc0c27e91936f3bbb83ecd7fda692ef101106289c5c2910e586a061ccdb8315d7e50fb73168a797d4e963a5058f077dc4fef911e3523d29b55ca9b1ee164d2d629f03e5937dd21c883966c212cf1de3cdc79da0d2a5e0bf8fe5041942536a17e1d560c080c3346087cb5d9aafdd7703c875a11bf7f2cdd44b64f83be65fe4",
15
+ "ic": [
16
+ "01ad96b8d94557fb0e599d74d6efacf2aa4b79eb95154bee16ecc2bb341300df0f2883242d52531e840e8b036d967118e46c7ae3b404771bc1f69a6744615f64",
17
+ "1eb5ce743d6e739b818dd89359c5f17de32a271a09a1f3ba83597e00621ed59f12f55c4b6d18bd4b42f1cd723045f238df1bca7852dba436b71cf0f21b1e2b6e",
18
+ "0440cfcbe09c27825d061222b7638c00d5696cd668ea597ab4a15674206b9b9e22f77b706aa53bf12a78e862e98ed83083787797acb28c52322b066964bf5ab4",
19
+ "22fdb5a3d9234f4440b8d8cbb8a9117348d0618139e2f1d5df3d9c6238d4eab62dff5fa539ee290fb5bdf76dd82817cdd034693023e775dad4688ab035088120",
20
+ "2eb22cc64a4848f0107b9bfc4b108d2a04fdf220fd4a42c0ea5d6f2cc9c9e24e1785dee6079cf7ec0b7f1963c98d3608b8f81900b96b061c036e23660adb1f85",
21
+ "0a4be75124046bca09901816bbb38a7815816ef4ea531057ebce60ee839cb72e20201653d9ebca2e691206c18611111280a17a0f6fab835d35ffd6b723ff3c37",
22
+ "009c32b9067eb596b86320cdeb35e459313b19b0505ec7aac01c57944dd648df151b97fbacf6a664070a10794502aaac1c5211e07a83d465194b5cbe90b016a9"
23
+ ],
24
+ "ceremony": "development single-party",
25
+ "ceremonyDetail": {
26
+ "ptau": "reused repo-local file (no download)",
27
+ "ptauBytes": 302072984,
28
+ "ptauPower": 18,
29
+ "r1csSha256": "46e3d6846000005db1a11559604dcf5efbcefa263eed78b0aef7702de91b6830",
30
+ "constraintCount": 87422,
31
+ "contribution": "enigma-sale-dev-1 (random entropy) + random beacon (10 iterations)"
32
+ },
33
+ "source": "sale_verification_key.json",
34
+ "createdAt": "2026-08-23T07:06:19.059Z"
35
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "format": "raw-be-hex-v1",
3
+ "curve": "bn128",
4
+ "g2LimbOrder": "c1c0",
5
+ "proofNote": "pi_a is raw — the on-chain program negates A",
6
+ "numPublicInputs": 6,
7
+ "icCount": 7,
8
+ "alphaG1": "2d4d9aa7e302d9df41749d5507949d05dbea33fbb16c643b22f599a2be6df2e214bedd503c37ceb061d8ec60209fe345ce89830a19230301f076caff004d1926",
9
+ "betaG2": "0967032fcbf776d1afc985f88877f182d38480a653f2decaa9794cbc3bf3060c0e187847ad4c798374d0d6732bf501847dd68bc0e071241e0213bc7fc13db7ab304cfbd1e08a704a99f5e847d93f8c3caafddec46b7a0d379da69a4d112346a71739c1b1a457a8c7313123d24d2f9192f896b7c63eea05a9d57f06547ad0cec8",
10
+ "gammaG2": "198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa",
11
+ "deltaG2": "091a85f20ac1f736ee31f97959685e8bd82ce0339ccfe72019b5966a1403f2991e5f3dcb18f308d4d546cfb0dcff42243a1b86329133565ea25c6f40a8adfe0620fbbb95e8fc21ae9c782ddb84189c406ba096b31e148fc8764690bf9288022a1b812a8b2155480b2e69b506eabb0c4f340ada0473ea711a0299abdb47da907e",
12
+ "ic": [
13
+ "2634587402f69103e89eab1748090987058ee27f71a2edfd2d7f5176aa81ac0805e814cb2ceb8751885f2860ca8f011b05a5db7f157b83662020d6d3be103698",
14
+ "06155bbf16ad4f3d5f57dc918444386a096c845bceef38336e7372225bc1b37b245257b11f5a3a7ac5b8400505cf29a0e68c7a2d50a2c9e60c2ba67ecad098f8",
15
+ "22582647eedd69991be9f13e3da959f9c39e209c8f173ea8c9a68b8d585415032ba3bbf4fdf5de4241231954c4632f484cea61b1b0471f078a22145ce8403914",
16
+ "2e3fb4f50e18ffcd44a1f469482338430d966156f08e63f2ead4c882be8f437704f308855af1ae4d41ff894f949c4b622f9ba7ebae461384f1514d9c9afa78df",
17
+ "2ab15cd0f9ff27527b9a5d405cc34ae38dbb3173819a867d5c924fd92d91288c2b283f34ca1cff31b47c684bb2002ca9361fc8d1e69902d9cf8ca4109652c547",
18
+ "06a396bcc77f20e5309a81c49dd3fc1bb458c377500319c80149a7c7e06f0e6d18f0871baaa62a63e2c4628c3e0584ce2d0610dbb77c72a7d3a8068dd6041281",
19
+ "084973788eda5f9a243f990e9429380d7869c680ef49e3986f1132470080388f046a01cf1d208c633c2102df3b5a2da26abb9e82b0b705e5f9150e6749bc7f90"
20
+ ],
21
+ "ceremony": {
22
+ "type": "single-party local (DEVELOPMENT ONLY — production needs a multi-party ceremony)",
23
+ "ptau": "reused existing file",
24
+ "ptauBytes": 302072984,
25
+ "r1csSha256": "558b99519e36fe94a0c7ffaed2cd5bb7865fc7387de42895e70dabba434c9656",
26
+ "constraintCount": 90897,
27
+ "powerOfTau": 18,
28
+ "contribution": "enigma-dev-1 (random entropy) + random beacon (10 iterations)"
29
+ },
30
+ "source": "verification_key.json",
31
+ "createdAt": "2026-08-23T07:05:43.317Z"
32
+ }
@@ -0,0 +1,64 @@
1
+ {
2
+ "version": 1,
3
+ "ceremony": "single-party development ceremony (2026-08-23) \u2014 production requires MPC",
4
+ "releaseBase": "https://github.com/Enigma-Memory/enigma-cortex-enterprise/releases/download/zk-assets-v1",
5
+ "circuits": {
6
+ "action_transition": {
7
+ "circuitVersion": 1,
8
+ "wasm": {
9
+ "file": "action_transition.wasm",
10
+ "sha256": "0e7abc6e4dcdf5869ccbc60f977e73bb24551a5004283ea6e96b22a43c9b6225",
11
+ "bytes": 2608957
12
+ },
13
+ "zkey": {
14
+ "file": "action_transition.zkey",
15
+ "sha256": "1b54596df69450c3b69128b10103188ccc9061a869fd7018cc939c68d7c1080c",
16
+ "bytes": 41534018
17
+ },
18
+ "r1csSha256": "558b99519e36fe94a0c7ffaed2cd5bb7865fc7387de42895e70dabba434c9656",
19
+ "vkBytes": {
20
+ "file": "vk_bytes.json",
21
+ "sha256": "e84987d4b4a0645214ef8b2cc91a883a922cdda7df9b9d435b745a3e0dce441c",
22
+ "bytes": 2595
23
+ }
24
+ },
25
+ "intent_attestation": {
26
+ "circuitVersion": 2,
27
+ "wasm": {
28
+ "file": "intent_attestation.wasm",
29
+ "sha256": "2c680fdf5c9503825612cb5ef8629e7a9316881cb83705dbf3b37cd05e5ea233",
30
+ "bytes": 4039469
31
+ },
32
+ "zkey": {
33
+ "file": "intent_attestation.zkey",
34
+ "sha256": "53927073b2b41bae6f817929779758cbe5869e6a6a455aab6a5f1e7475e019dd",
35
+ "bytes": 10335105
36
+ },
37
+ "r1csSha256": "c485c9bb702d9db158ffeffa023ca24dd425764cdc876fadfbc63da5d8efef5d",
38
+ "vkBytes": {
39
+ "file": "intent_vk_bytes.json",
40
+ "sha256": "851f6d898e8b1877ff3081dcbfab61ca76ad72d2747e9d7648f6d9e4a06420d4",
41
+ "bytes": 2652
42
+ }
43
+ },
44
+ "sealed_sale_release": {
45
+ "circuitVersion": 3,
46
+ "wasm": {
47
+ "file": "sealed_sale_release.wasm",
48
+ "sha256": "98c204a8fb9ab507d84962331c9c01b37f53d454699dcfd1e063f157962e9d79",
49
+ "bytes": 5568152
50
+ },
51
+ "zkey": {
52
+ "file": "sealed_sale_release.zkey",
53
+ "sha256": "8c577a3dfaa64477440397ace1ed61f817a3d533307d236abbe4251c76666ff2",
54
+ "bytes": 41163791
55
+ },
56
+ "r1csSha256": "46e3d6846000005db1a11559604dcf5efbcefa263eed78b0aef7702de91b6830",
57
+ "vkBytes": {
58
+ "file": "sale_vk_bytes.json",
59
+ "sha256": "a746456055c2f9521bb6cc2b3b569eea5ff2170662b73643bb3954fc774dfbe2",
60
+ "bytes": 2649
61
+ }
62
+ }
63
+ }
64
+ }
@@ -0,0 +1,87 @@
1
+ # Enigma ZK End-to-End Build Contract v3 (binding; supersedes v2)
2
+
3
+ ## Architecture: sovereign per-action ZK proofs (single layer)
4
+ Every shared-state transition is a client-generated Groth16 proof. User secrets
5
+ (ownerKey, rho, payload openings, Merkle paths) NEVER leave the client — no
6
+ sequencer/relayer ever sees a witness. Relayers submit only proof + public inputs.
7
+ On-chain Poseidon does not exist, so BOTH appends and revocations are proven.
8
+
9
+ Design note (recorded decision): a two-layer admission(PendingAction)+epoch-batch
10
+ split was evaluated and rejected — binding admitted nullifiers into an epoch proof
11
+ requires either on-chain Poseidon (unavailable) or in-circuit SHA-256 (~400k extra
12
+ constraints). Client-side proving of the full IMT transition is 5-15s WASM —
13
+ affordable — so the single-layer design preserves sovereignty without the binding
14
+ hole. Batch/recursive aggregation remains a documented future optimization.
15
+
16
+ ## On-chain contract (main agent implementing; DO NOT touch program source)
17
+ - SharedState PDA [b"shared_state"]: authority, note_root, null_root,
18
+ note_count u64, null_count u64, created_at.
19
+ - initialize_shared_state(genesis_note_root, genesis_null_root) — governance
20
+ (live upgrade-authority check). Genesis values from the JS zero-chain/IMT genesis.
21
+ - settle_action(proof{a[64],b[128],c[64]} raw BE — program negates A internally,
22
+ public_inputs[[u8;32];6]) — permissionless (relayer-friendly; any payer).
23
+ Program: canonicality (< r) on all 6; continuity old roots == stored roots;
24
+ unpack packed = mode*2^60 + action_index; mode 0 (append): nullifier MUST be 0,
25
+ action_index == note_count → note_count++; mode 1 (revoke): action_index ==
26
+ null_count → null_count++; Groth16 verify vs pinned VK (IC len 7); store new roots;
27
+ emit ActionSettled. Stale roots → tx fails → client regenerates within ~2 slots
28
+ (documented contention model, ~70-85 settles/block/account CU ceiling).
29
+ - KEEP: initialize_registry, register_commitment, record_revocation (non-ZK
30
+ owner-signed path), initialize_circuit_verifying_key (IC len now 7).
31
+ - REMOVE: RootIndex/RootShard/register_zk_root/verify_zk_memory_proof (wave-1 dead).
32
+
33
+ ## 6 public inputs, exact order (canonical BE < r = 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001)
34
+ [0] oldNoteRoot [1] newNoteRoot [2] oldNullRoot [3] newNullRoot
35
+ [4] nullifier (0 for append; nf for revoke)
36
+ [5] packed = mode * 2^60 + actionIndex (mode ∈ {0,1}; actionIndex < 2^60)
37
+
38
+ ## Circuit: cortex-v3/circuits/action_transition.circom — ActionTransition(D=20)
39
+ Poseidon (circomlib), BN254. Public signal names/order exactly as above.
40
+ Private: isAppend (boolean-constrained), note, ownerKey, rho, payloadCommit,
41
+ notePathElements[D], notePathIndices[D] (LSB-first bits),
42
+ noteMemPathElements[D], noteMemPathIndices[D],
43
+ predValue, predNextIndex, predNextValue, predPathElements[D], predPathIndices[D],
44
+ appendPathElements[D], appendPathIndices[D].
45
+
46
+ ### APPEND mode (isAppend=1; packed mode=0)
47
+ - zeros[0]=0, zeros[i+1]=Poseidon(zeros[i],zeros[i]) in-circuit.
48
+ - Verify zero-leaf (zeros[D]) path at actionIndex against oldNoteRoot.
49
+ - newNoteRoot = root with leaf=note inserted at actionIndex.
50
+ - Constrain newNullRoot == oldNullRoot; nullifier === 0.
51
+ - Note well-formedness in BOTH modes: note === Poseidon([ownerKey, rho, payloadCommit])
52
+ so an appended note is always bound to its owner's key.
53
+
54
+ ### REVOKE mode (isAppend=0)
55
+ - Membership: note path vs oldNoteRoot. newNoteRoot == oldNoteRoot.
56
+ - nf = Poseidon([DOMAIN_REVOCATION, ownerKey, rho]); nullifier === nf.
57
+ DOMAIN_REVOCATION = 0x656e69676d615f7265766f6b65 ("enigma_revoke") field constant.
58
+ - IMT (Aztec-style): leaf hash = Poseidon([value, nextIndex, nextValue]); genesis
59
+ index 0 = {0, 0, r-1}; prove predecessor path vs oldNullRoot; strict
60
+ predValue < nf < predNextValue (bit-decomposition comparisons); updated predecessor
61
+ = {predValue, actionIndex, nf} → intermediate root; append new leaf
62
+ {nf, predNextIndex, predNextValue} at actionIndex (zero-leaf path vs intermediate
63
+ root) → newNullRoot.
64
+
65
+ Constraint target 60-120k → ptau 2^18 (powersOfTau28_hez_final_18.ptau).
66
+
67
+ ## Toolchain
68
+ - circom: iden3/circom release binary → cargo install --locked fallback → WSL.
69
+ - snarkjs, circomlib, circomlibjs via npm -D in cortex-v3.
70
+ - Setup: single-party DEV ceremony (groth16 setup + contribute + beacon) — docs MUST
71
+ state production needs multi-party ceremony.
72
+
73
+ ## File ownership
74
+ - Main agent: programs/enigma_nullifier/**, idl/**, tests/enigma_nullifier.ts,
75
+ scripts/test-governance-localnet.mjs, this contract.
76
+ - CircuitBuild: circuits/** (+ circomlib devDep).
77
+ - CodecSetup: zk/zk-codec.mjs, zk/zk-codec.test.mjs, zk/setup.mjs, ptau/**,
78
+ circuits/build/** outputs (verification_key.json + vk_bytes.json COMMITTABLE;
79
+ gitignore ptau/, *.zkey, *.r1cs, wasm). IC length MUST be 7.
80
+ - TreeWitness: zk/zk-tree.mjs, zk/witness.mjs (buildActionWitness), zk/zk-tree.test.mjs
81
+ (+ circomlibjs devDep).
82
+
83
+ ## Claim boundaries (hard)
84
+ - Dev ceremony ≠ production trusted setup. Nullifiers = protocol non-use, never
85
+ deletion. No "first on Solana" until publicly reproducible end-to-end.
86
+ - Sovereignty invariant: no private witness material in ANY network-facing payload;
87
+ test-zk-e2e MUST assert the submitted tx contains only proof + public inputs.