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
@@ -0,0 +1,184 @@
1
+ // witness.mjs — buildActionWitness: client-side snarkjs input for
2
+ // circuits/action_transition.circom — ActionTransition(D=20).
3
+ //
4
+ // Binding spec: cortex-v3/zk/BUILD-CONTRACT.md v3 (sovereign per-action proofs).
5
+ // RECONCILIATION POINT: circuits/action_transition.circom did not exist when
6
+ // this file was written; every signal name below is taken VERBATIM from
7
+ // BUILD-CONTRACT.md v3, so no name drift is expected. If the circuit diverges,
8
+ // this file is the single place to reconcile.
9
+ //
10
+ // Public signals (exact order/names): oldNoteRoot, newNoteRoot, oldNullRoot,
11
+ // newNullRoot, nullifier, packed.
12
+ // Private signals: isAppend, note, ownerKey, rho, payloadCommit,
13
+ // notePathElements[D], notePathIndices[D],
14
+ // noteMemPathElements[D], noteMemPathIndices[D],
15
+ // predValue, predNextIndex, predNextValue,
16
+ // predPathElements[D], predPathIndices[D],
17
+ // appendPathElements[D], appendPathIndices[D].
18
+ //
19
+ // packed = mode * 2^60 + actionIndex, where the ON-WIRE mode is 0=append,
20
+ // 1=revoke (NOTE the inversion vs the circuit boolean: isAppend=1 ⇔ mode=0).
21
+ // actionIndex = note_count (append) / null_count (revoke); null_count counts
22
+ // the IMT genesis leaf, so an untouched IMT has null_count == 1 and the first
23
+ // revocation appends at index 1.
24
+ //
25
+ // All field elements are emitted as DECIMAL STRINGS (snarkjs JSON convention).
26
+ //
27
+ // Mutation contract: APPEND mutates noteTree (inserts the note) and leaves
28
+ // nullifierTree untouched; REVOKE mutates nullifierTree (IMT insert) and leaves
29
+ // noteTree untouched. The emitted old* roots are the pre-mutation roots — build
30
+ // the witness, then submit; on stale-root rejection rebuild against fresh state.
31
+
32
+ import {
33
+ DOMAIN_REVOCATION,
34
+ NoteTree,
35
+ NullifierIMT,
36
+ TREE_DEPTH,
37
+ poseidon,
38
+ } from "./zk-tree.mjs";
39
+
40
+ const D = TREE_DEPTH;
41
+ const ZERO_PATH_ELEMENTS = Object.freeze(Array.from({ length: D }, () => 0n));
42
+ const ZERO_PATH_INDICES = Object.freeze(Array.from({ length: D }, () => 0));
43
+
44
+ /** Recursively convert bigints → decimal strings for snarkjs input JSON. */
45
+ function toDec(x) {
46
+ if (typeof x === "bigint") return x.toString(10);
47
+ if (Array.isArray(x)) return x.map(toDec);
48
+ if (typeof x === "number") return String(x);
49
+ if (typeof x === "object" && x !== null) {
50
+ return Object.fromEntries(Object.entries(x).map(([k, v]) => [k, toDec(v)]));
51
+ }
52
+ return x;
53
+ }
54
+
55
+ function need(value, name) {
56
+ if (value === undefined || value === null) throw new TypeError(`buildActionWitness: missing ${name}`);
57
+ return BigInt(value);
58
+ }
59
+
60
+ /**
61
+ * Build the snarkjs input for one sovereign action.
62
+ *
63
+ * @param {object} args
64
+ * @param {"append"|"revoke"} args.mode
65
+ * @param {NoteTree} args.noteTree note tree at the current on-chain note_root
66
+ * @param {NullifierIMT} args.nullifierTree IMT at the current on-chain null_root
67
+ * @param {bigint|number|string} args.ownerKey note opening
68
+ * @param {bigint|number|string} args.rho note opening
69
+ * @param {bigint|number|string} args.payloadCommit note opening
70
+ * @param {bigint|number|string} [args.note] optional; asserted equal to
71
+ * Poseidon([ownerKey, rho, payloadCommit]) when given
72
+ * @param {number} [args.noteIndex] REVOKE only: index of the note in noteTree
73
+ * @returns {object} snarkjs input JSON (all values decimal strings)
74
+ */
75
+ export function buildActionWitness(args) {
76
+ const { mode, noteTree, nullifierTree } = args;
77
+ if (!(noteTree instanceof NoteTree)) throw new TypeError("noteTree must be a NoteTree");
78
+ if (!(nullifierTree instanceof NullifierIMT)) {
79
+ throw new TypeError("nullifierTree must be a NullifierIMT");
80
+ }
81
+ const ownerKey = need(args.ownerKey, "ownerKey");
82
+ const rho = need(args.rho, "rho");
83
+ const payloadCommit = need(args.payloadCommit, "payloadCommit");
84
+ // Note well-formedness (enforced by the circuit in BOTH modes):
85
+ // note === Poseidon([ownerKey, rho, payloadCommit]).
86
+ const note = poseidon([ownerKey, rho, payloadCommit]);
87
+ if (args.note !== undefined && BigInt(args.note) !== note) {
88
+ throw new Error("provided note does not match Poseidon([ownerKey, rho, payloadCommit])");
89
+ }
90
+
91
+ const oldNoteRoot = noteTree.root();
92
+ const oldNullRoot = nullifierTree.root();
93
+
94
+ let isAppend;
95
+ let packedMode;
96
+ let actionIndex;
97
+ let nullifier;
98
+ let newNoteRoot;
99
+ let newNullRoot;
100
+ let notePathElements = ZERO_PATH_ELEMENTS;
101
+ let notePathIndices = ZERO_PATH_INDICES;
102
+ let noteMemPathElements = ZERO_PATH_ELEMENTS;
103
+ let noteMemPathIndices = ZERO_PATH_INDICES;
104
+ let predValue = 0n;
105
+ let predNextIndex = 0n;
106
+ let predNextValue = 0n;
107
+ let predPathElements = ZERO_PATH_ELEMENTS;
108
+ let predPathIndices = ZERO_PATH_INDICES;
109
+ let appendPathElements = ZERO_PATH_ELEMENTS;
110
+ let appendPathIndices = ZERO_PATH_INDICES;
111
+
112
+ if (mode === "append") {
113
+ isAppend = 1;
114
+ packedMode = 0n;
115
+ nullifier = 0n;
116
+ // actionIndex == on-chain note_count == next sequential insert index.
117
+ actionIndex = BigInt(noteTree.nextIndex);
118
+ const ins = noteTree.insert(note); // pre-insert zero-leaf proof, then mutate
119
+ notePathElements = ins.pathElements;
120
+ notePathIndices = ins.pathIndices;
121
+ newNoteRoot = noteTree.root();
122
+ newNullRoot = oldNullRoot; // constrained equal by the circuit
123
+ } else if (mode === "revoke") {
124
+ isAppend = 0;
125
+ packedMode = 1n;
126
+ const noteIndex = args.noteIndex;
127
+ if (!Number.isInteger(noteIndex) || noteIndex < 0 || noteIndex >= noteTree.nextIndex) {
128
+ throw new RangeError(`noteIndex ${noteIndex} not present in note tree`);
129
+ }
130
+ if (noteTree.leaves[noteIndex] !== note) {
131
+ throw new Error("note opening does not match the leaf at noteIndex");
132
+ }
133
+ // Membership of note in the note tree vs oldNoteRoot.
134
+ const mem = noteTree.getProof(noteIndex);
135
+ noteMemPathElements = mem.pathElements;
136
+ noteMemPathIndices = mem.pathIndices;
137
+ // Deterministic, epoch-independent, domain-separated nullifier:
138
+ // nf = Poseidon([DOMAIN_REVOCATION, ownerKey, rho]).
139
+ nullifier = poseidon([DOMAIN_REVOCATION, ownerKey, rho]);
140
+ // actionIndex == on-chain null_count == IMT sequential append index.
141
+ actionIndex = BigInt(nullifierTree.appendCounter);
142
+ const ins = nullifierTree.insert(nullifier); // throws on duplicate nf
143
+ predValue = ins.predecessorLeaf.value;
144
+ predNextIndex = ins.predecessorLeaf.nextIndex;
145
+ predNextValue = ins.predecessorLeaf.nextValue;
146
+ predPathElements = ins.predecessorPath.pathElements;
147
+ predPathIndices = ins.predecessorPath.pathIndices;
148
+ appendPathElements = ins.appendPath.pathElements;
149
+ appendPathIndices = ins.appendPath.pathIndices;
150
+ newNoteRoot = oldNoteRoot; // constrained equal by the circuit
151
+ newNullRoot = nullifierTree.root();
152
+ } else {
153
+ throw new Error(`unknown mode ${JSON.stringify(mode)} (expected "append" | "revoke")`);
154
+ }
155
+
156
+ const packed = packedMode * (1n << 60n) + actionIndex;
157
+
158
+ return toDec({
159
+ // public (exact contract order/names)
160
+ oldNoteRoot,
161
+ newNoteRoot,
162
+ oldNullRoot,
163
+ newNullRoot,
164
+ nullifier,
165
+ packed,
166
+ // private
167
+ isAppend,
168
+ note,
169
+ ownerKey,
170
+ rho,
171
+ payloadCommit,
172
+ notePathElements,
173
+ notePathIndices,
174
+ noteMemPathElements,
175
+ noteMemPathIndices,
176
+ predValue,
177
+ predNextIndex,
178
+ predNextValue,
179
+ predPathElements,
180
+ predPathIndices,
181
+ appendPathElements,
182
+ appendPathIndices,
183
+ });
184
+ }
@@ -0,0 +1,232 @@
1
+ /**
2
+ * zk-codec.mjs — snarkjs JSON → raw big-endian byte codec for the Enigma
3
+ * action-transition Groth16 verifier (Solana alt_bn128).
4
+ *
5
+ * Binding spec: cortex-v3/zk/BUILD-CONTRACT.md (v3).
6
+ *
7
+ * Conventions (BINDING):
8
+ * - All G1 points: 64 bytes, x||y, each a 32-byte big-endian base-field (Fq)
9
+ * element. Decimal strings in snarkjs JSON → 32B BE.
10
+ * - All G2 points: 128 bytes. snarkjs JSON encodes each Fq2 coordinate as
11
+ * [c0, c1] (real, imaginary). The alt_bn128 / EIP-196 precompile expects
12
+ * (im, re) = (c1, c0). Default output order is therefore "c1c0"; the
13
+ * `g2LimbOrder: "c0c1"` option exists for empirical on-chain resolution.
14
+ * - Proof point A is passed through RAW — the on-chain program negates A.
15
+ * NEVER negate here.
16
+ * - Public inputs: 32B BE each, MUST be canonical (< Fr). Violation throws.
17
+ * - Verifying key IC length MUST equal expectedIc (default 7 = ic[0] + 6
18
+ * public inputs of ActionTransition).
19
+ */
20
+
21
+ /** BN254 scalar field modulus r (Fr). */
22
+ export const FR_MODULUS = BigInt(
23
+ "0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001",
24
+ );
25
+
26
+ /** BN254 base field modulus q (Fq, curve coordinates). */
27
+ export const FQ_MODULUS = BigInt(
28
+ "0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47",
29
+ );
30
+
31
+ /** Number of public inputs of the ActionTransition circuit (v3 contract). */
32
+ export const NUM_PUBLIC_INPUTS = 6;
33
+
34
+ /** Expected IC length: ic[0] + NUM_PUBLIC_INPUTS. */
35
+ export const EXPECTED_IC_LENGTH = NUM_PUBLIC_INPUTS + 1;
36
+
37
+ const G1_BYTES = 64;
38
+ const G2_BYTES = 128;
39
+ const SCALAR_BYTES = 32;
40
+
41
+ function parseJson(maybeJson, what) {
42
+ if (typeof maybeJson === "string") {
43
+ try {
44
+ return JSON.parse(maybeJson);
45
+ } catch (err) {
46
+ throw new Error(`zk-codec: ${what} is not valid JSON: ${err.message}`);
47
+ }
48
+ }
49
+ if (maybeJson === null || typeof maybeJson !== "object") {
50
+ throw new Error(`zk-codec: ${what} must be a JSON object or JSON string`);
51
+ }
52
+ return maybeJson;
53
+ }
54
+
55
+ function toBigIntDecimal(value, what) {
56
+ if (typeof value === "bigint") return value;
57
+ if (typeof value === "number") {
58
+ if (!Number.isSafeInteger(value) || value < 0) {
59
+ throw new Error(`zk-codec: ${what} is not a non-negative safe integer`);
60
+ }
61
+ return BigInt(value);
62
+ }
63
+ if (typeof value === "string") {
64
+ if (!/^(0|[1-9][0-9]*)$/.test(value)) {
65
+ throw new Error(`zk-codec: ${what} is not a canonical decimal string: ${JSON.stringify(value)}`);
66
+ }
67
+ return BigInt(value);
68
+ }
69
+ throw new Error(`zk-codec: ${what} has unsupported type ${typeof value}`);
70
+ }
71
+
72
+ /** Field element (canonical, < modulus) → 32-byte big-endian Buffer. */
73
+ function fieldToBytes32BE(value, modulus, what) {
74
+ const n = toBigIntDecimal(value, what);
75
+ if (n < 0n || n >= modulus) {
76
+ throw new Error(
77
+ `zk-codec: ${what} is not canonical (must satisfy 0 <= value < ${modulus}); got ${n}`,
78
+ );
79
+ }
80
+ const buf = Buffer.alloc(SCALAR_BYTES);
81
+ let v = n;
82
+ for (let i = SCALAR_BYTES - 1; i >= 0; i--) {
83
+ buf[i] = Number(v & 0xffn);
84
+ v >>= 8n;
85
+ }
86
+ return buf;
87
+ }
88
+
89
+ /** Scalar-field element (< Fr) → 32B BE. Throws on non-canonical input. */
90
+ export function frToBytes32BE(value) {
91
+ return fieldToBytes32BE(value, FR_MODULUS, "Fr scalar");
92
+ }
93
+
94
+ /** Base-field element (< Fq) → 32B BE. Throws on non-canonical input. */
95
+ export function fqToBytes32BE(value) {
96
+ return fieldToBytes32BE(value, FQ_MODULUS, "Fq coordinate");
97
+ }
98
+
99
+ function assertG1Shape(p, what) {
100
+ if (!Array.isArray(p) || p.length < 2) {
101
+ throw new Error(`zk-codec: ${what} must be an array [x, y, ...]`);
102
+ }
103
+ }
104
+
105
+ function assertG2Shape(p, what) {
106
+ if (
107
+ !Array.isArray(p) ||
108
+ p.length < 2 ||
109
+ !Array.isArray(p[0]) ||
110
+ p[0].length < 2 ||
111
+ !Array.isArray(p[1]) ||
112
+ p[1].length < 2
113
+ ) {
114
+ throw new Error(`zk-codec: ${what} must be [[x_c0, x_c1], [y_c0, y_c1], ...]`);
115
+ }
116
+ }
117
+
118
+ /** snarkjs G1 [x, y, ...] → 64B BE x||y. */
119
+ export function g1ToBytes(point, what = "G1 point") {
120
+ assertG1Shape(point, what);
121
+ return Buffer.concat([
122
+ fqToBytes32BE(point[0]),
123
+ fqToBytes32BE(point[1]),
124
+ ]);
125
+ }
126
+
127
+ function normalizeG2LimbOrder(order) {
128
+ if (order === "c1c0" || order === "c0c1") return order;
129
+ throw new Error(`zk-codec: g2LimbOrder must be "c1c0" or "c0c1", got ${JSON.stringify(order)}`);
130
+ }
131
+
132
+ /**
133
+ * snarkjs G2 [[x_c0, x_c1], [y_c0, y_c1], ...] → 128B BE.
134
+ * g2LimbOrder "c1c0" (default, EIP-196/alt_bn128 (im,re)):
135
+ * x_c1||x_c0||y_c1||y_c0
136
+ * g2LimbOrder "c0c1": x_c0||x_c1||y_c0||y_c1
137
+ */
138
+ export function g2ToBytes(point, g2LimbOrder = "c1c0", what = "G2 point") {
139
+ normalizeG2LimbOrder(g2LimbOrder);
140
+ assertG2Shape(point, what);
141
+ const [xc0, xc1] = point[0];
142
+ const [yc0, yc1] = point[1];
143
+ const limbs =
144
+ g2LimbOrder === "c1c0"
145
+ ? [xc1, xc0, yc1, yc0]
146
+ : [xc0, xc1, yc0, yc1];
147
+ return Buffer.concat(limbs.map((l) => fqToBytes32BE(l)));
148
+ }
149
+
150
+ /**
151
+ * snarkjs verification_key.json → raw BE verifying key bytes.
152
+ *
153
+ * @param {object|string} vkJson parsed vk or JSON string.
154
+ * @param {object} [opts]
155
+ * @param {"c1c0"|"c0c1"} [opts.g2LimbOrder="c1c0"] G2 limb order (default c1c0
156
+ * = alt_bn128/EIP-196 (im,re)).
157
+ * @param {number} [opts.expectedIc=7] required IC length (ic[0] + 6 public
158
+ * inputs for ActionTransition). Throws on mismatch.
159
+ * @returns {{alphaG1: Buffer, betaG2: Buffer, gammaG2: Buffer, deltaG2: Buffer, ic: Buffer[]}}
160
+ * alphaG1 64B; betaG2/gammaG2/deltaG2 128B; ic = expectedIc × 64B.
161
+ */
162
+ export function vkFromSnarkjs(vkJson, opts = {}) {
163
+ const { g2LimbOrder = "c1c0", expectedIc = EXPECTED_IC_LENGTH } = opts;
164
+ normalizeG2LimbOrder(g2LimbOrder);
165
+ if (!Number.isInteger(expectedIc) || expectedIc < 1) {
166
+ throw new Error(`zk-codec: expectedIc must be a positive integer, got ${expectedIc}`);
167
+ }
168
+ const vk = parseJson(vkJson, "verification key");
169
+ for (const k of ["vk_alpha_1", "vk_beta_2", "vk_gamma_2", "vk_delta_2", "IC"]) {
170
+ if (!(k in vk)) throw new Error(`zk-codec: verification key missing field "${k}"`);
171
+ }
172
+ if (!Array.isArray(vk.IC)) {
173
+ throw new Error("zk-codec: verification key IC must be an array");
174
+ }
175
+ if (vk.IC.length !== expectedIc) {
176
+ throw new Error(
177
+ `zk-codec: verification key IC length ${vk.IC.length} != expected ${expectedIc} ` +
178
+ `(ic[0] + ${expectedIc - 1} public inputs)`,
179
+ );
180
+ }
181
+ return {
182
+ alphaG1: g1ToBytes(vk.vk_alpha_1, "vk_alpha_1"),
183
+ betaG2: g2ToBytes(vk.vk_beta_2, g2LimbOrder, "vk_beta_2"),
184
+ gammaG2: g2ToBytes(vk.vk_gamma_2, g2LimbOrder, "vk_gamma_2"),
185
+ deltaG2: g2ToBytes(vk.vk_delta_2, g2LimbOrder, "vk_delta_2"),
186
+ ic: vk.IC.map((p, i) => g1ToBytes(p, `IC[${i}]`)),
187
+ };
188
+ }
189
+
190
+ /**
191
+ * snarkjs proof.json → raw BE proof bytes for settle_epoch.
192
+ * A is passed through RAW — the on-chain program negates A. NEVER negate here.
193
+ *
194
+ * @param {object|string} proofJson parsed proof or JSON string.
195
+ * @param {object} [opts]
196
+ * @param {"c1c0"|"c0c1"} [opts.g2LimbOrder="c1c0"]
197
+ * @returns {{a: Buffer, b: Buffer, c: Buffer}} a 64B, b 128B, c 64B.
198
+ */
199
+ export function proofFromSnarkjs(proofJson, opts = {}) {
200
+ const { g2LimbOrder = "c1c0" } = opts;
201
+ normalizeG2LimbOrder(g2LimbOrder);
202
+ const proof = parseJson(proofJson, "proof");
203
+ for (const k of ["pi_a", "pi_b", "pi_c"]) {
204
+ if (!(k in proof)) throw new Error(`zk-codec: proof missing field "${k}"`);
205
+ }
206
+ return {
207
+ a: g1ToBytes(proof.pi_a, "pi_a"),
208
+ b: g2ToBytes(proof.pi_b, g2LimbOrder, "pi_b"),
209
+ c: g1ToBytes(proof.pi_c, "pi_c"),
210
+ };
211
+ }
212
+
213
+ /**
214
+ * snarkjs public.json (array of decimal strings) → array of 32B BE buffers.
215
+ * Every element MUST be canonical (< Fr = r); non-canonical values throw.
216
+ *
217
+ * @param {Array<string|number|bigint>|string} publicJson parsed array or JSON string.
218
+ * @returns {Buffer[]} one 32-byte BE buffer per public input.
219
+ */
220
+ export function publicInputsFromSnarkjs(publicJson) {
221
+ const arr = parseJson(publicJson, "public inputs");
222
+ if (!Array.isArray(arr)) {
223
+ throw new Error("zk-codec: public inputs must be an array of decimal strings");
224
+ }
225
+ return arr.map((v, i) => fieldToBytes32BE(v, FR_MODULUS, `public input [${i}]`));
226
+ }
227
+
228
+ export const BYTE_LENGTHS = Object.freeze({
229
+ G1: G1_BYTES,
230
+ G2: G2_BYTES,
231
+ SCALAR: SCALAR_BYTES,
232
+ });