@ottochain/sdk 2.3.0 → 2.5.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.
Files changed (287) hide show
  1. package/dist/cjs/apps/compute/index.js +33 -0
  2. package/dist/cjs/apps/compute/state-machines/compute-rule110.js +164 -0
  3. package/dist/cjs/apps/compute/state-machines/index.js +9 -0
  4. package/dist/cjs/apps/contracts/index.js +16 -9
  5. package/dist/cjs/apps/contracts/state-machines/contract-agreement.js +134 -161
  6. package/dist/cjs/apps/contracts/state-machines/contract-escrow.js +192 -170
  7. package/dist/cjs/apps/contracts/state-machines/contract-universal.js +46 -58
  8. package/dist/cjs/apps/corporate/index.js +2 -2
  9. package/dist/cjs/apps/corporate/state-machines/corp-board.js +500 -456
  10. package/dist/cjs/apps/corporate/state-machines/corp-entity.js +487 -361
  11. package/dist/cjs/apps/corporate/state-machines/corp-securities.js +769 -576
  12. package/dist/cjs/apps/corporate/state-machines/corp-shareholders.js +567 -557
  13. package/dist/cjs/apps/governance/index.js +21 -21
  14. package/dist/cjs/apps/governance/state-machines/dao-multisig.js +188 -209
  15. package/dist/cjs/apps/governance/state-machines/dao-reputation.js +181 -228
  16. package/dist/cjs/apps/governance/state-machines/dao-single.js +105 -88
  17. package/dist/cjs/apps/governance/state-machines/dao-token.js +199 -227
  18. package/dist/cjs/apps/governance/state-machines/governance-simple.js +231 -231
  19. package/dist/cjs/apps/governance/state-machines/governance-universal.js +64 -64
  20. package/dist/cjs/apps/identity/constants.js +55 -22
  21. package/dist/cjs/apps/identity/index.js +28 -12
  22. package/dist/cjs/apps/identity/state-machines/identity-agent.js +124 -158
  23. package/dist/cjs/apps/identity/state-machines/identity-oracle.js +158 -173
  24. package/dist/cjs/apps/identity/state-machines/identity-registry.js +262 -0
  25. package/dist/cjs/apps/identity/state-machines/identity-universal.js +51 -57
  26. package/dist/cjs/apps/identity/state-machines/index.js +3 -1
  27. package/dist/cjs/apps/index.js +22 -8
  28. package/dist/cjs/apps/lending/assets.js +247 -0
  29. package/dist/cjs/apps/lending/credit-scoring.js +87 -0
  30. package/dist/cjs/apps/lending/eligibility.js +105 -0
  31. package/dist/cjs/apps/lending/index.js +91 -0
  32. package/dist/cjs/apps/lending/state-machines/index.js +9 -0
  33. package/dist/cjs/apps/lending/state-machines/lending-zk-loan.js +433 -0
  34. package/dist/cjs/apps/markets/index.js +22 -12
  35. package/dist/cjs/apps/markets/state-machines/market-auction.js +116 -134
  36. package/dist/cjs/apps/markets/state-machines/market-crowdfund.js +131 -141
  37. package/dist/cjs/apps/markets/state-machines/market-group-buy.js +163 -184
  38. package/dist/cjs/apps/markets/state-machines/market-prediction.js +226 -233
  39. package/dist/cjs/apps/markets/state-machines/market-universal.js +65 -80
  40. package/dist/cjs/apps/oracles/index.js +3 -3
  41. package/dist/cjs/apps/privacy/index.js +67 -0
  42. package/dist/cjs/apps/privacy/state-machines/index.js +17 -0
  43. package/dist/cjs/apps/privacy/state-machines/mixer-ddhRing.js +286 -0
  44. package/dist/cjs/apps/privacy/state-machines/note-pool.js +476 -0
  45. package/dist/cjs/apps/staked-pool/assets.js +103 -0
  46. package/dist/cjs/apps/staked-pool/base.js +498 -0
  47. package/dist/cjs/apps/staked-pool/consumer.js +55 -0
  48. package/dist/cjs/apps/staked-pool/index.js +83 -0
  49. package/dist/cjs/apps/staked-pool/state-machines/index.js +12 -0
  50. package/dist/cjs/apps/staked-pool/state-machines/staked-pool-base.js +49 -0
  51. package/dist/cjs/apps/staked-pool/state-machines/staked-pool-oracle.js +131 -0
  52. package/dist/cjs/errors.js +3 -3
  53. package/dist/cjs/generated/google/protobuf/struct.js +5 -5
  54. package/dist/cjs/generated/google/protobuf/timestamp.js +1 -1
  55. package/dist/cjs/generated/index.js +11 -7
  56. package/dist/cjs/generated/openapi.js +6 -0
  57. package/dist/cjs/generated/ottochain/apps/contracts/v1/contract.js +51 -51
  58. package/dist/cjs/generated/ottochain/apps/corporate/v1/corporate.js +20 -21
  59. package/dist/cjs/generated/ottochain/apps/governance/v1/governance.js +14 -14
  60. package/dist/cjs/generated/ottochain/apps/identity/v1/attestation.js +5 -5
  61. package/dist/cjs/generated/ottochain/apps/identity/v1/identity.js +125 -131
  62. package/dist/cjs/generated/ottochain/apps/markets/v1/market.js +108 -108
  63. package/dist/cjs/generated/ottochain/v1/common.js +5 -5
  64. package/dist/cjs/generated/ottochain/v1/fiber.js +44 -6
  65. package/dist/cjs/generated/ottochain/v1/messages.js +1 -1
  66. package/dist/cjs/generated/ottochain/v1/records.js +1 -1
  67. package/dist/cjs/index.js +58 -7
  68. package/dist/cjs/openapi.js +2 -0
  69. package/dist/cjs/ottochain/drop-nulls.js +1 -2
  70. package/dist/cjs/ottochain/genesis-manifest.js +17 -11
  71. package/dist/cjs/ottochain/index.js +23 -13
  72. package/dist/cjs/ottochain/metagraph-client.js +81 -16
  73. package/dist/cjs/ottochain/snapshot.js +13 -16
  74. package/dist/cjs/ottochain/transaction.js +67 -14
  75. package/dist/cjs/ottochain/types.js +16 -2
  76. package/dist/cjs/privacy/index.js +14 -0
  77. package/dist/cjs/privacy/sealed-bid.js +213 -0
  78. package/dist/cjs/privacy/shield-app.js +131 -0
  79. package/dist/cjs/schema/effects.js +156 -0
  80. package/dist/cjs/schema/fiber-app.js +150 -15
  81. package/dist/cjs/schema/guard-lint.js +343 -0
  82. package/dist/cjs/schema/guards.js +246 -0
  83. package/dist/cjs/signing.js +80 -0
  84. package/dist/cjs/templates/asset-policy.js +190 -0
  85. package/dist/cjs/templates/index.js +86 -0
  86. package/dist/cjs/templates/machine.js +130 -0
  87. package/dist/cjs/templates/migration.js +39 -0
  88. package/dist/cjs/templates/state-shape.js +38 -0
  89. package/dist/cjs/types.js +2 -3
  90. package/dist/cjs/validation.js +9 -11
  91. package/dist/cjs/verify.js +9 -4
  92. package/dist/cjs/zk/commit.js +53 -0
  93. package/dist/cjs/zk/guard.js +107 -0
  94. package/dist/cjs/zk/index.js +48 -0
  95. package/dist/cjs/zk/preimage.js +37 -0
  96. package/dist/cjs/zk/prover.js +87 -0
  97. package/dist/cjs/zk/registry.js +62 -0
  98. package/dist/cjs/zk/types.js +28 -0
  99. package/dist/cjs/zk/witness.js +19 -0
  100. package/dist/esm/apps/compute/index.js +29 -0
  101. package/dist/esm/apps/compute/state-machines/compute-rule110.js +161 -0
  102. package/dist/esm/apps/compute/state-machines/index.js +5 -0
  103. package/dist/esm/apps/contracts/index.js +9 -5
  104. package/dist/esm/apps/contracts/state-machines/contract-agreement.js +135 -162
  105. package/dist/esm/apps/contracts/state-machines/contract-escrow.js +193 -171
  106. package/dist/esm/apps/contracts/state-machines/contract-universal.js +47 -59
  107. package/dist/esm/apps/corporate/index.js +2 -2
  108. package/dist/esm/apps/corporate/state-machines/corp-board.js +501 -457
  109. package/dist/esm/apps/corporate/state-machines/corp-entity.js +488 -362
  110. package/dist/esm/apps/corporate/state-machines/corp-securities.js +770 -577
  111. package/dist/esm/apps/corporate/state-machines/corp-shareholders.js +568 -558
  112. package/dist/esm/apps/governance/index.js +10 -10
  113. package/dist/esm/apps/governance/state-machines/dao-multisig.js +189 -210
  114. package/dist/esm/apps/governance/state-machines/dao-reputation.js +182 -229
  115. package/dist/esm/apps/governance/state-machines/dao-single.js +106 -89
  116. package/dist/esm/apps/governance/state-machines/dao-token.js +200 -228
  117. package/dist/esm/apps/governance/state-machines/governance-simple.js +232 -232
  118. package/dist/esm/apps/governance/state-machines/governance-universal.js +65 -65
  119. package/dist/esm/apps/identity/constants.js +52 -21
  120. package/dist/esm/apps/identity/index.js +14 -9
  121. package/dist/esm/apps/identity/state-machines/identity-agent.js +125 -159
  122. package/dist/esm/apps/identity/state-machines/identity-oracle.js +159 -174
  123. package/dist/esm/apps/identity/state-machines/identity-registry.js +259 -0
  124. package/dist/esm/apps/identity/state-machines/identity-universal.js +52 -58
  125. package/dist/esm/apps/identity/state-machines/index.js +1 -0
  126. package/dist/esm/apps/index.js +9 -5
  127. package/dist/esm/apps/lending/assets.js +231 -0
  128. package/dist/esm/apps/lending/credit-scoring.js +81 -0
  129. package/dist/esm/apps/lending/eligibility.js +99 -0
  130. package/dist/esm/apps/lending/index.js +69 -0
  131. package/dist/esm/apps/lending/state-machines/index.js +5 -0
  132. package/dist/esm/apps/lending/state-machines/lending-zk-loan.js +430 -0
  133. package/dist/esm/apps/markets/index.js +11 -7
  134. package/dist/esm/apps/markets/state-machines/market-auction.js +117 -135
  135. package/dist/esm/apps/markets/state-machines/market-crowdfund.js +132 -142
  136. package/dist/esm/apps/markets/state-machines/market-group-buy.js +164 -185
  137. package/dist/esm/apps/markets/state-machines/market-prediction.js +227 -234
  138. package/dist/esm/apps/markets/state-machines/market-universal.js +66 -81
  139. package/dist/esm/apps/oracles/index.js +3 -3
  140. package/dist/esm/apps/privacy/index.js +56 -0
  141. package/dist/esm/apps/privacy/state-machines/index.js +6 -0
  142. package/dist/esm/apps/privacy/state-machines/mixer-ddhRing.js +282 -0
  143. package/dist/esm/apps/privacy/state-machines/note-pool.js +470 -0
  144. package/dist/esm/apps/staked-pool/assets.js +91 -0
  145. package/dist/esm/apps/staked-pool/base.js +493 -0
  146. package/dist/esm/apps/staked-pool/consumer.js +49 -0
  147. package/dist/esm/apps/staked-pool/index.js +60 -0
  148. package/dist/esm/apps/staked-pool/state-machines/index.js +6 -0
  149. package/dist/esm/apps/staked-pool/state-machines/staked-pool-base.js +46 -0
  150. package/dist/esm/apps/staked-pool/state-machines/staked-pool-oracle.js +127 -0
  151. package/dist/esm/generated/google/protobuf/struct.js +1 -1
  152. package/dist/esm/generated/google/protobuf/timestamp.js +1 -1
  153. package/dist/esm/generated/index.js +9 -5
  154. package/dist/esm/generated/openapi.js +5 -0
  155. package/dist/esm/generated/ottochain/apps/contracts/v1/contract.js +47 -47
  156. package/dist/esm/generated/ottochain/apps/corporate/v1/corporate.js +1 -1
  157. package/dist/esm/generated/ottochain/apps/governance/v1/governance.js +1 -1
  158. package/dist/esm/generated/ottochain/apps/identity/v1/attestation.js +1 -1
  159. package/dist/esm/generated/ottochain/apps/identity/v1/identity.js +115 -121
  160. package/dist/esm/generated/ottochain/apps/markets/v1/market.js +101 -101
  161. package/dist/esm/generated/ottochain/v1/common.js +1 -1
  162. package/dist/esm/generated/ottochain/v1/fiber.js +40 -2
  163. package/dist/esm/generated/ottochain/v1/messages.js +1 -1
  164. package/dist/esm/generated/ottochain/v1/records.js +1 -1
  165. package/dist/esm/index.js +28 -3
  166. package/dist/esm/openapi.js +1 -0
  167. package/dist/esm/ottochain/genesis-manifest.js +15 -9
  168. package/dist/esm/ottochain/index.js +2 -3
  169. package/dist/esm/ottochain/metagraph-client.js +81 -16
  170. package/dist/esm/ottochain/snapshot.js +6 -8
  171. package/dist/esm/ottochain/transaction.js +51 -3
  172. package/dist/esm/ottochain/types.js +15 -1
  173. package/dist/esm/privacy/index.js +6 -0
  174. package/dist/esm/privacy/sealed-bid.js +209 -0
  175. package/dist/esm/privacy/shield-app.js +127 -0
  176. package/dist/esm/schema/effects.js +145 -0
  177. package/dist/esm/schema/fiber-app.js +139 -8
  178. package/dist/esm/schema/guard-lint.js +337 -0
  179. package/dist/esm/schema/guards.js +228 -0
  180. package/dist/esm/signing.js +74 -0
  181. package/dist/esm/templates/asset-policy.js +182 -0
  182. package/dist/esm/templates/index.js +41 -0
  183. package/dist/esm/templates/machine.js +125 -0
  184. package/dist/esm/templates/migration.js +34 -0
  185. package/dist/esm/templates/state-shape.js +34 -0
  186. package/dist/esm/validation.js +1 -3
  187. package/dist/esm/verify.js +8 -2
  188. package/dist/esm/zk/commit.js +44 -0
  189. package/dist/esm/zk/guard.js +99 -0
  190. package/dist/esm/zk/index.js +19 -0
  191. package/dist/esm/zk/preimage.js +30 -0
  192. package/dist/esm/zk/prover.js +82 -0
  193. package/dist/esm/zk/registry.js +55 -0
  194. package/dist/esm/zk/types.js +25 -0
  195. package/dist/esm/zk/witness.js +15 -0
  196. package/dist/types/apps/compute/index.d.ts +176 -0
  197. package/dist/types/apps/compute/state-machines/compute-rule110.d.ts +157 -0
  198. package/dist/types/apps/compute/state-machines/index.d.ts +5 -0
  199. package/dist/types/apps/contracts/index.d.ts +81 -221
  200. package/dist/types/apps/contracts/state-machines/contract-agreement.d.ts +23 -98
  201. package/dist/types/apps/contracts/state-machines/contract-escrow.d.ts +49 -115
  202. package/dist/types/apps/contracts/state-machines/contract-universal.d.ts +4 -4
  203. package/dist/types/apps/corporate/index.d.ts +1176 -440
  204. package/dist/types/apps/corporate/state-machines/corp-board.d.ts +271 -135
  205. package/dist/types/apps/corporate/state-machines/corp-entity.d.ts +279 -74
  206. package/dist/types/apps/corporate/state-machines/corp-securities.d.ts +373 -149
  207. package/dist/types/apps/corporate/state-machines/corp-shareholders.d.ts +252 -80
  208. package/dist/types/apps/governance/index.d.ts +368 -470
  209. package/dist/types/apps/governance/state-machines/dao-multisig.d.ts +92 -107
  210. package/dist/types/apps/governance/state-machines/dao-reputation.d.ts +61 -85
  211. package/dist/types/apps/governance/state-machines/dao-single.d.ts +25 -47
  212. package/dist/types/apps/governance/state-machines/dao-token.d.ts +79 -68
  213. package/dist/types/apps/governance/state-machines/governance-simple.d.ts +95 -125
  214. package/dist/types/apps/governance/state-machines/governance-universal.d.ts +6 -6
  215. package/dist/types/apps/identity/constants.d.ts +33 -5
  216. package/dist/types/apps/identity/index.d.ts +415 -131
  217. package/dist/types/apps/identity/state-machines/identity-agent.d.ts +23 -23
  218. package/dist/types/apps/identity/state-machines/identity-oracle.d.ts +27 -98
  219. package/dist/types/apps/identity/state-machines/identity-registry.d.ts +379 -0
  220. package/dist/types/apps/identity/state-machines/identity-universal.d.ts +4 -4
  221. package/dist/types/apps/identity/state-machines/index.d.ts +1 -0
  222. package/dist/types/apps/index.d.ts +9 -5
  223. package/dist/types/apps/lending/assets.d.ts +258 -0
  224. package/dist/types/apps/lending/credit-scoring.d.ts +80 -0
  225. package/dist/types/apps/lending/eligibility.d.ts +83 -0
  226. package/dist/types/apps/lending/index.d.ts +556 -0
  227. package/dist/types/apps/lending/state-machines/index.d.ts +5 -0
  228. package/dist/types/apps/lending/state-machines/lending-zk-loan.d.ts +536 -0
  229. package/dist/types/apps/markets/index.d.ts +181 -276
  230. package/dist/types/apps/markets/state-machines/market-auction.d.ts +25 -49
  231. package/dist/types/apps/markets/state-machines/market-crowdfund.d.ts +35 -53
  232. package/dist/types/apps/markets/state-machines/market-group-buy.d.ts +35 -61
  233. package/dist/types/apps/markets/state-machines/market-prediction.d.ts +65 -86
  234. package/dist/types/apps/markets/state-machines/market-universal.d.ts +12 -12
  235. package/dist/types/apps/oracles/index.d.ts +1 -1
  236. package/dist/types/apps/privacy/index.d.ts +328 -0
  237. package/dist/types/apps/privacy/state-machines/index.d.ts +6 -0
  238. package/dist/types/apps/privacy/state-machines/mixer-ddhRing.d.ts +337 -0
  239. package/dist/types/apps/privacy/state-machines/note-pool.d.ts +196 -0
  240. package/dist/types/apps/staked-pool/assets.d.ts +53 -0
  241. package/dist/types/apps/staked-pool/base.d.ts +80 -0
  242. package/dist/types/apps/staked-pool/consumer.d.ts +29 -0
  243. package/dist/types/apps/staked-pool/index.d.ts +51 -0
  244. package/dist/types/apps/staked-pool/state-machines/index.d.ts +6 -0
  245. package/dist/types/apps/staked-pool/state-machines/staked-pool-base.d.ts +8 -0
  246. package/dist/types/apps/staked-pool/state-machines/staked-pool-oracle.d.ts +34 -0
  247. package/dist/types/generated/index.d.ts +5 -5
  248. package/dist/types/generated/openapi.d.ts +1270 -0
  249. package/dist/types/generated/ottochain/apps/contracts/v1/contract.d.ts +5 -5
  250. package/dist/types/generated/ottochain/apps/identity/v1/identity.d.ts +12 -12
  251. package/dist/types/generated/ottochain/apps/markets/v1/market.d.ts +11 -11
  252. package/dist/types/generated/ottochain/v1/fiber.d.ts +7 -0
  253. package/dist/types/index.d.ts +7 -3
  254. package/dist/types/openapi.d.ts +24 -0
  255. package/dist/types/ottochain/genesis-manifest.d.ts +11 -5
  256. package/dist/types/ottochain/index.d.ts +5 -6
  257. package/dist/types/ottochain/metagraph-client.d.ts +49 -7
  258. package/dist/types/ottochain/snapshot.d.ts +6 -6
  259. package/dist/types/ottochain/transaction.d.ts +41 -1
  260. package/dist/types/ottochain/types.d.ts +336 -31
  261. package/dist/types/privacy/index.d.ts +6 -0
  262. package/dist/types/privacy/sealed-bid.d.ts +348 -0
  263. package/dist/types/privacy/shield-app.d.ts +48 -0
  264. package/dist/types/schema/effects.d.ts +141 -0
  265. package/dist/types/schema/fiber-app.d.ts +282 -2
  266. package/dist/types/schema/guard-lint.d.ts +111 -0
  267. package/dist/types/schema/guards.d.ts +146 -0
  268. package/dist/types/signing.d.ts +45 -0
  269. package/dist/types/templates/asset-policy.d.ts +119 -0
  270. package/dist/types/templates/index.d.ts +26 -0
  271. package/dist/types/templates/machine.d.ts +139 -0
  272. package/dist/types/templates/migration.d.ts +34 -0
  273. package/dist/types/templates/state-shape.d.ts +30 -0
  274. package/dist/types/validation.d.ts +22 -217
  275. package/dist/types/verify.d.ts +4 -0
  276. package/dist/types/zk/commit.d.ts +28 -0
  277. package/dist/types/zk/guard.d.ts +46 -0
  278. package/dist/types/zk/index.d.ts +19 -0
  279. package/dist/types/zk/preimage.d.ts +10 -0
  280. package/dist/types/zk/prover.d.ts +34 -0
  281. package/dist/types/zk/registry.d.ts +34 -0
  282. package/dist/types/zk/types.d.ts +33 -0
  283. package/dist/types/zk/witness.d.ts +40 -0
  284. package/package.json +47 -15
  285. package/dist/cjs/ottochain/normalize.js +0 -186
  286. package/dist/esm/ottochain/normalize.js +0 -179
  287. package/dist/types/ottochain/normalize.d.ts +0 -79
@@ -0,0 +1,127 @@
1
+ /**
2
+ * shieldApp — turn a fiber app into a PRIVATE-state pool.
3
+ *
4
+ * Given a base {@link FiberAppDefinition} (the app whose state + transition you want to keep
5
+ * private), `shieldApp` returns a new `FiberAppDefinition` for a "shielded pool" Machine fiber.
6
+ * The pool's state is PUBLIC scaffolding only — the spent-nullifier set, the commitment log, and
7
+ * the set of valid anchors — while the app's real state lives off-chain in a note committed to
8
+ * the tree. Each app transition is carried out off-chain and attested by a single
9
+ * `zk-jlvm-shielded` Groth16 proof; the on-chain combine just verifies the proof, rejects an
10
+ * already-spent nullifier, and records the new commitment.
11
+ *
12
+ * Division of labour (see ottochain-sdk RFC docs/design/zk-private-contract-state-rfc.md):
13
+ * - the CIRCUIT proves membership ∧ authorization ∧ `jlvm-core` effect ∧ new commitment;
14
+ * - this GUARD (combine) verifies the proof, pins which app logic ran (`exprHash`), checks the
15
+ * anchor is recent, and checks the nullifier is fresh — all combiner-only (CLAUDE.md);
16
+ * - block-validity stays structural (proof / publicValues present + hex).
17
+ *
18
+ * It uses NO new metakit opcode: `groth16_verify` verifies the proof, and the four-`bytes32`
19
+ * public values (`anchor`, `nullifier`, `newCommitment`, `exprHash`) are extracted from the
20
+ * VERIFIED `publicValues` string with fixed-offset `substr` — slicing the verified bytes IS the
21
+ * binding (§8.1).
22
+ *
23
+ * NOTE on cost: the note model rehashes the whole state each transition, so proving cost is
24
+ * O(state size) (RFC §8). Keep shielded note state small (a few KB); for large keyed state use
25
+ * the auth-DB variant (RFC §3.1.1).
26
+ */
27
+ import { defineFiberApp } from '../schema/fiber-app.js';
28
+ /**
29
+ * Field extractors over the abi-encoded `JlvmTransitionPublicValues` — four static `bytes32`
30
+ * `[anchor | nullifier | newCommitment | exprHash]`, a fixed 128-byte (256 hex char) layout with
31
+ * NO dynamic arrays. `publicValues` is the 0x-prefixed hex from the prover, so each field is 64
32
+ * hex chars starting at: anchor=2, nullifier=66, newCommitment=130, exprHash=194.
33
+ */
34
+ const pvField = (publicValues, hexOffset) => ({
35
+ substr: [publicValues, hexOffset, 64],
36
+ });
37
+ /** Standard public state every shielded pool carries (the rest of the app state is private/off-chain). */
38
+ export const SHIELDED_POOL_STATE = {
39
+ vkey: { type: 'hash', immutable: true },
40
+ exprHash: { type: 'hash', immutable: true },
41
+ rootWindow: { type: 'integer', immutable: true },
42
+ currentRoot: { type: 'hash', computed: true },
43
+ knownRoots: { type: 'array', computed: true, description: 'rolling window of valid anchors (hex)' },
44
+ nullifiers: { type: 'array', computed: true, description: 'spent set (hex); monotonic — see RFC §5.3' },
45
+ commitments: { type: 'array', computed: true, description: 'append-only log of output commitments (hex)' },
46
+ leafCount: { type: 'integer', computed: true, default: 0 },
47
+ transitions: { type: 'integer', computed: true, default: 0 },
48
+ };
49
+ /**
50
+ * Build the shielded-pool variant of `base`.
51
+ *
52
+ * @param base the app being shielded (used for naming + to document the pinned logic).
53
+ * @param opts the circuit vkey + the pinned `exprHash` + the anchor window.
54
+ */
55
+ export function shieldApp(base, opts) {
56
+ const publicValues = { var: 'event.publicValues' };
57
+ const anchor = pvField(publicValues, 2);
58
+ const nullifier = pvField(publicValues, 66);
59
+ const newCommitment = pvField(publicValues, 130);
60
+ const exprHash = pvField(publicValues, 194);
61
+ // GUARD (combine): all stateful, combiner-only.
62
+ const guard = {
63
+ and: [
64
+ // 1. the proof verifies against the pool's pinned vkey over EXACTLY these public bytes
65
+ { groth16_verify: [{ var: 'state.vkey' }, publicValues, { var: 'event.proof' }] },
66
+ // 2. it ran the app logic this pool pins (binds which effect produced the transition)
67
+ { '===': [exprHash, { var: 'state.exprHash' }] },
68
+ // 3. the spent note was proven under an anchor we still honor
69
+ { in: [anchor, { var: 'state.knownRoots' }] },
70
+ // 4. inter-transfer double-spend guard: the nullifier is not already spent
71
+ { none: [{ var: 'state.nullifiers' }, { '===': [{ var: '' }, nullifier] }] },
72
+ ],
73
+ };
74
+ // EFFECT (combine): spend the nullifier, record the new commitment, advance counters.
75
+ // Root advancement (turning the appended commitment into the next anchor) is wallet/Bridge-side
76
+ // per RFC §6.2 / §10; the chain records the commitment + nullifier here.
77
+ const effect = {
78
+ merge: [
79
+ { var: 'state' },
80
+ {
81
+ nullifiers: { cat: [{ var: 'state.nullifiers' }, [nullifier]] },
82
+ commitments: { cat: [{ var: 'state.commitments' }, [newCommitment]] },
83
+ leafCount: { '+': [{ var: 'state.leafCount' }, 1] },
84
+ transitions: { '+': [{ var: 'state.transitions' }, 1] },
85
+ lastTransitionAt: { var: '$ordinal' },
86
+ },
87
+ ],
88
+ };
89
+ return defineFiberApp({
90
+ metadata: {
91
+ name: `Shielded${base.metadata.name}`,
92
+ app: 'privacy',
93
+ type: `shielded-${base.metadata.type}`,
94
+ version: base.metadata.version,
95
+ description: `Shielded (zk-jlvm-shielded) variant of ${base.metadata.name}: private state transitions ` +
96
+ `verified by a Groth16 proof; the nullifier set + anchors are public pool state.`,
97
+ },
98
+ createSchema: {
99
+ required: ['vkey', 'exprHash'],
100
+ properties: {
101
+ vkey: { type: 'hash', immutable: true, default: opts.vkey },
102
+ exprHash: { type: 'hash', immutable: true, default: opts.exprHash },
103
+ rootWindow: { type: 'integer', immutable: true, default: opts.rootWindow ?? 64 },
104
+ },
105
+ },
106
+ stateSchema: { properties: { ...SHIELDED_POOL_STATE } },
107
+ eventSchemas: {
108
+ transition: {
109
+ description: `A private state transition of ${base.metadata.name}, attested by a zk-jlvm-shielded Groth16 proof.`,
110
+ required: ['proof', 'publicValues'],
111
+ properties: {
112
+ proof: { type: 'string', description: 'Groth16 proof bytes (0x hex)' },
113
+ publicValues: { type: 'string', description: 'abi-encoded JlvmTransitionPublicValues (4×bytes32, 0x hex)' },
114
+ },
115
+ },
116
+ },
117
+ states: {
118
+ ACTIVE: {
119
+ id: 'ACTIVE',
120
+ isFinal: false,
121
+ metadata: { label: 'Active', description: 'Pool accepts shielded transitions', category: 'active' },
122
+ },
123
+ },
124
+ initialState: 'ACTIVE',
125
+ transitions: [{ from: 'ACTIVE', to: 'ACTIVE', eventName: 'transition', guard, effect, dependencies: [] }],
126
+ });
127
+ }
@@ -0,0 +1,145 @@
1
+ /**
2
+ * Builders for the fiber-engine reserved EFFECT directives — the `_`-prefixed keys the chain extracts
3
+ * from an evaluated effect result and applies as side effects (then strips from the merged state).
4
+ *
5
+ * Place the returned fragment INSIDE the state-update map of a `merge` effect, so the directive rides in
6
+ * the evaluated result map (EffectExtractor reads it; StateMerger drops `_`-prefixed keys from state):
7
+ *
8
+ * ```ts
9
+ * effect: {
10
+ * merge: [
11
+ * { var: "state" },
12
+ * { boundAt: { var: "$ordinal" }, ...addDependency({ var: "event.registryId" }) },
13
+ * ],
14
+ * }
15
+ * ```
16
+ */
17
+ /**
18
+ * `_addDependency` (#24): add — or re-activate — a runtime DYNAMIC dependency on `fiberId`, so that
19
+ * fiber's state appears in `machines.<fiberId>` for SUBSEQUENT transitions of this fiber. `fiberId` may
20
+ * be a literal UUID string or an expression (e.g. `{ var: "event.registryId" }`, `{ var: "state.registryId" }`).
21
+ * The ledger is append-only, idempotent (one entry per fiber), and engine-bounded (active + ledger caps).
22
+ * Because the `machines` context is built BEFORE the effect runs, the bound dependency is readable only
23
+ * from the NEXT transition onward (two-phase: bind, then read).
24
+ */
25
+ export const addDependency = (fiberId) => ({
26
+ _addDependency: [{ fiberId }],
27
+ });
28
+ /**
29
+ * `_setDependencyActive` (#24): toggle a dynamic dependency's `active` flag. The entry is NEVER removed —
30
+ * deactivation simply drops it from the `machines` context (and it can be cheaply re-activated). `fiberId`
31
+ * may be a literal or an expression.
32
+ */
33
+ export const setDependencyActive = (fiberId, active) => ({
34
+ _setDependencyActive: [{ fiberId, active }],
35
+ });
36
+ /**
37
+ * `_transferAsset`: move one or more WHOLE asset instances the emitting fiber holds, each to a single
38
+ * recipient. The directive rides INSIDE a `merge` effect map (the engine extracts `_`-prefixed keys
39
+ * before merging into state); a transition-level `emits` block is silently stripped by
40
+ * `toProtoDefinition`, which would strand the asset.
41
+ *
42
+ * Each directive is `{ assetId, recipient }` ONLY — there is NO `amount` field. The combiner reassigns
43
+ * `holder := recipient` on the WHOLE asset record (`AssetCombiner.applyFiberTransfer`); value is moved
44
+ * one whole instance at a time, never split. `recipient` must resolve to the canonical `AssetHolder`
45
+ * OBJECT form — `{"Fiber":{"fiberId":..}}` / `{"Wallet":{"address":..}}` — built with {@link toFiber} /
46
+ * {@link toWallet}; the chain raises a graceful `CombineRejected` on a bare string or malformed object
47
+ * (`EffectExtractor.parseAssetTransfer`). `assetId` is a UUID; the holder id may be a literal or an
48
+ * expression (e.g. `{ var: "event.agent" }`).
49
+ *
50
+ * Combiner-side holder defense (R1) independently re-validates every directive: the asset must resolve,
51
+ * be held by `Fiber(self)`, be `behavior.transferable`, and (Fiber recipient) the recipient fiber must be
52
+ * live — else the whole transition is `CombineRejected`. There is a hard cap of 32 asset mutations per
53
+ * transition (all-or-nothing); keep emitting fibers at ≤1 transfer per transition for claim/withdraw/slash.
54
+ *
55
+ * @example
56
+ * effect: { merge: [ { var: "state" }, {
57
+ * status: "SETTLED",
58
+ * ...transferAsset([{ assetId: { var: "event.rewardAssetId" }, recipient: toWallet({ var: "event.agent" }) }]),
59
+ * } ] }
60
+ */
61
+ export const transferAsset = (transfers) => ({ _transferAsset: transfers });
62
+ /**
63
+ * Build a `_transferAsset` `recipient` as the canonical `AssetHolder` OBJECT form. The chain requires the
64
+ * object form ONLY — `{"Fiber":{"fiberId":..}}` / `{"Wallet":{"address":..}}` — and raises a graceful
65
+ * `CombineRejected` on a bare string or a malformed object (`EffectExtractor.parseAssetTransfer`); the
66
+ * legacy bare-string UUID/DAG-address disambiguation has been removed. These mirror the typed
67
+ * {@link fiberHolder} / {@link walletHolder} `AssetHolder` builders (used for `MintAsset.holder` /
68
+ * `ApplyMorphism.recipient`) but accept a `JsonLogicValue`, so the id can be a runtime expression:
69
+ *
70
+ * ```ts
71
+ * transferAsset([{ assetId, recipient: toFiber({ var: "event.retailerId" }) }]); // → {"Fiber":{"fiberId":..}}
72
+ * transferAsset([{ assetId, recipient: toWallet({ var: "event.agent" }) }]); // → {"Wallet":{"address":..}}
73
+ * ```
74
+ */
75
+ export const toFiber = (fiberId) => ({
76
+ Fiber: { fiberId },
77
+ });
78
+ /** See {@link toFiber}: a `transferAsset` recipient held by a wallet — `{"Wallet":{"address":..}}`. */
79
+ export const toWallet = (address) => ({
80
+ Wallet: { address },
81
+ });
82
+ /**
83
+ * `_triggers` (F4): fire one or more CROSS-FIBER events. Each entry is projected to
84
+ * `{ targetMachineId, eventName, payload }` — the exact shape the chain's `EffectExtractor` reads
85
+ * (`ReservedKeys.scala`, `EffectExtractor.scala`). `target` is the recipient fiber id (a literal UUID
86
+ * or an expression, e.g. `{ var: "event.retailerId" }`); `event` is the event NAME to enqueue on it;
87
+ * `payload` is the event body — omit it and the builder emits `{}` (never `null`).
88
+ *
89
+ * Authoring this as a builder makes a typo'd `_trigger` / `triggres` a TypeScript error rather than a
90
+ * silently-merged state field (the F4 foot-gun). Place the fragment INSIDE the effect's state-update
91
+ * map so it rides in the evaluated result the extractor reads.
92
+ *
93
+ * @example
94
+ * effect: { merge: [ { var: "state" }, {
95
+ * status: "debt_current",
96
+ * ...triggers([{ target: { var: "event.retailerId" }, event: "process_sale",
97
+ * payload: { buyerId: { var: "machineId" }, quantity: { var: "event.quantity" } } }]),
98
+ * } ] }
99
+ */
100
+ export const triggers = (ts) => ({
101
+ _triggers: ts.map((t) => ({
102
+ targetMachineId: t.target,
103
+ eventName: t.event,
104
+ payload: t.payload ?? {},
105
+ })),
106
+ });
107
+ /**
108
+ * `_spawn`: create one or more CHILD fibers, each from a literal machine `definition`. Each entry is
109
+ * `{ childId, definition, initialData, owners }` (`ReservedKeys.scala`, `EffectExtractor.scala`).
110
+ *
111
+ * The chain extracts `_spawn` from the effect EXPRESSION, not the evaluated result, so `definition`
112
+ * MUST be a literal {@link ProtoStateMachineDefinition} (e.g. a nested `machine().wireDefinition()` /
113
+ * `toProtoDefinition(child)` output) — NOT an expression the engine would evaluate at runtime.
114
+ *
115
+ * F8 gotcha — `owners` is load-bearing. A spawned child's transitions are gated by
116
+ * `owners ∪ authorizedSigners` (`riverdale-economy/README.md`), so EVERY party that will later drive
117
+ * the child (e.g. every bidder on a spawned auction) MUST be listed in `owners`, or their events are
118
+ * rejected. `owners` may be a literal id array or an expression (e.g. `{ var: "event.auctionOwners" }`);
119
+ * `childId` / `initialData` likewise accept literals or expressions.
120
+ */
121
+ export const spawn = (ds) => ({ _spawn: ds });
122
+ /**
123
+ * `_emit`: emit one or more domain events to the fiber's outbox. Each entry is
124
+ * `{ name, data, destination? }` (`ReservedKeys.scala`, `EffectExtractor.scala`). `name` is the event
125
+ * name, `data` the body (a literal or an expression), and `destination` an OPTIONAL routing target —
126
+ * omit it when absent (callers never pass `null`, so it is simply absent on the wire).
127
+ */
128
+ export const emit = (es) => ({
129
+ _emit: es,
130
+ });
131
+ /**
132
+ * The complete set of `_`-prefixed RESERVED effect keys the chain's `EffectExtractor` consumes and
133
+ * `StateMerger` strips from state (`ReservedKeys.scala:12-49`). Exported so a validator (Proposal 01)
134
+ * can reject an unknown `_`-prefixed key (a typo'd directive) instead of letting it silently leak into
135
+ * persisted state.
136
+ */
137
+ export const RESERVED_EFFECT_KEYS = [
138
+ '_triggers',
139
+ '_spawn',
140
+ '_emit',
141
+ '_transferAsset',
142
+ '_scriptCall',
143
+ '_addDependency',
144
+ '_setDependencyActive',
145
+ ];
@@ -4,6 +4,121 @@
4
4
  * TypeScript-first definitions for fiber apps. This is the source of truth —
5
5
  * no JSON, no code generation. Import types directly.
6
6
  */
7
+ /**
8
+ * The wire (and authoring) tag for the `Immutable` policy VARIANT: the bare JSON string
9
+ * `"Immutable"`. EXACT casing, capital-I — this is the POLICY-LEVEL variant name and is
10
+ * DISTINCT from the `upgradePolicy` dial VALUE `"immutable"` (lowercase). The chain emits
11
+ * exactly this capital-I string for `Immutable`, so the SDK must too, byte-for-byte.
12
+ */
13
+ export const IMMUTABLE_POLICY = 'Immutable';
14
+ /** The names of the 15 policy dials, in declaration order. Used by the projector. */
15
+ const FIBER_POLICY_DIALS = [
16
+ 'selfReproducing',
17
+ 'allowedEffects',
18
+ 'spawnOwnerPolicy',
19
+ 'maxGenerations',
20
+ 'maxSpawnFanout',
21
+ 'acceptedCallers',
22
+ 'sealedStates',
23
+ 'transitionPolicy',
24
+ 'transferPolicy',
25
+ 'dependencyPolicy',
26
+ 'upgradePolicy',
27
+ 'version',
28
+ 'compatibleWith',
29
+ 'interfaces',
30
+ 'migrationAuthority',
31
+ ];
32
+ /**
33
+ * The canonical UNCONSTRAINED policy: omission. Provided as a named export for
34
+ * readability at call sites — `policy: unconstrained()` documents intent, and projects
35
+ * to NO `policy` key (identical to leaving `policy` off entirely).
36
+ */
37
+ export function unconstrained() {
38
+ return undefined;
39
+ }
40
+ /**
41
+ * The canonical IMMUTABLE policy: the definition is permanently locked. Projects to the
42
+ * bare JSON string `"Immutable"` ({@link IMMUTABLE_POLICY}), the chain's `Immutable`
43
+ * variant tag. Semantically equivalent to `constrained({ upgradePolicy: 'immutable' })`
44
+ * with no other dial set — which `constrained()`/`projectFiberPolicy()` collapse to the
45
+ * same string for wire parity (see {@link constrained}).
46
+ *
47
+ * @example
48
+ * ```ts
49
+ * const def = defineFiberApp({ ...spec, policy: immutable() });
50
+ * ```
51
+ */
52
+ export function immutable() {
53
+ return IMMUTABLE_POLICY;
54
+ }
55
+ /**
56
+ * Build a CONSTRAINED `FiberPolicy` from any subset of the 15 dials.
57
+ *
58
+ * Pass only the dials you want to set. Dials left `undefined`/`null` are dropped so the
59
+ * result is a clean, minimal object that serializes identically to the chain's
60
+ * `dropNulls`-stripped `Constrained`. If NO dial is effectively set, this returns
61
+ * `undefined` (an empty constraint == `Unconstrained`), which projects to no `policy`
62
+ * key — preserving wire parity.
63
+ *
64
+ * CANONICAL COLLAPSE: `constrained({ upgradePolicy: 'immutable' })` with NO other dial set
65
+ * collapses to the bare string `"Immutable"` ({@link IMMUTABLE_POLICY}), because the chain
66
+ * collapses that exact `Constrained` into the `Immutable` variant. NOTE the casing: the
67
+ * collapse triggers on the chain's LOWERCASE upgradePolicy dial value `"immutable"`, and
68
+ * the result is the capital-I policy-variant tag `"Immutable"`. Signing the dials object
69
+ * `{ "upgradePolicy": "immutable" }` instead would diverge the canonical (the chain
70
+ * re-encodes it as `"Immutable"`) and break the create signature. Adding ANY other dial
71
+ * keeps it a dials object.
72
+ *
73
+ * @example
74
+ * ```ts
75
+ * const policy = constrained({
76
+ * selfReproducing: false,
77
+ * maxGenerations: 3,
78
+ * allowedEffects: ['EMIT', 'TRANSFER'],
79
+ * sealedStates: ['ARCHIVED'],
80
+ * });
81
+ * ```
82
+ */
83
+ export function constrained(dials) {
84
+ const out = {};
85
+ for (const k of FIBER_POLICY_DIALS) {
86
+ const v = dials[k];
87
+ if (v === undefined || v === null)
88
+ continue;
89
+ out[k] = v;
90
+ }
91
+ const keys = Object.keys(out);
92
+ if (keys.length === 0)
93
+ return undefined;
94
+ // Canonical collapse: a lone LOWERCASE `upgradePolicy: 'immutable'` (the chain's dial
95
+ // value) IS the `Immutable` variant — emit the capital-I `"Immutable"` tag, not the dials.
96
+ if (keys.length === 1 && out.upgradePolicy === 'immutable')
97
+ return IMMUTABLE_POLICY;
98
+ return out;
99
+ }
100
+ /**
101
+ * Project an authoring `policy` value onto the wire form. Returns one of:
102
+ * - `undefined` when the policy is (effectively) `Unconstrained` — i.e. omit the `policy`
103
+ * key entirely;
104
+ * - the bare string `"Immutable"` ({@link IMMUTABLE_POLICY}) for the `Immutable` variant
105
+ * (also the collapse of a lone LOWERCASE `upgradePolicy: 'immutable'`); or
106
+ * - the minimal `Constrained` dials object otherwise.
107
+ *
108
+ * Centralizes the omit-on-unconstrained AND the Immutable-collapse parity rules so every
109
+ * projection path (`toProtoDefinition`, the genesis manifest) stays consistent.
110
+ */
111
+ export function projectFiberPolicy(policy) {
112
+ if (policy === undefined || policy === null)
113
+ return undefined;
114
+ // The Immutable variant is already its canonical bare-string wire form.
115
+ if (policy === IMMUTABLE_POLICY)
116
+ return IMMUTABLE_POLICY;
117
+ // Re-run the dial filter so a hand-built object with explicit-undefined/empty dials
118
+ // collapses to Unconstrained, and a lone `upgradePolicy: 'immutable'` collapses to
119
+ // `"Immutable"`, exactly like `constrained()` does.
120
+ return constrained(policy);
121
+ }
7
122
  // =============================================================================
8
123
  // Helper: defineFiberApp
9
124
  // =============================================================================
@@ -31,11 +146,11 @@ export function defineFiberApp(definition) {
31
146
  }
32
147
  /** Get valid transitions from a given state */
33
148
  export function getTransitionsFrom(def, state) {
34
- return def.transitions.filter(t => t.from === state);
149
+ return def.transitions.filter((t) => t.from === state);
35
150
  }
36
151
  /** Get valid event names from a given state */
37
152
  export function getEventsFrom(def, state) {
38
- return getTransitionsFrom(def, state).map(t => t.eventName);
153
+ return getTransitionsFrom(def, state).map((t) => t.eventName);
39
154
  }
40
155
  /** Check if a state is final */
41
156
  export function isFinalState(def, state) {
@@ -62,14 +177,19 @@ export function toProtoDefinition(def) {
62
177
  const protoDef = {
63
178
  states: {},
64
179
  initialState: def.initialState,
65
- transitions: def.transitions.map(t => ({
180
+ transitions: def.transitions.map((t) => ({
66
181
  from: t.from,
67
182
  to: t.to,
68
183
  eventName: t.eventName,
69
184
  guard: t.guard, // Required - Scala has no default
70
185
  effect: t.effect, // Required - Scala has no default
71
- // dependencies has default Set.empty in Scala, so omit if empty
72
- ...(t.dependencies?.length && { dependencies: [...t.dependencies] }),
186
+ // Chain `Transition.dependencies: Set[UUID]` is REQUIRED (no Scala default), and each
187
+ // element must be a fiber UUID string. A `DependencySpec` object is a build-time-only
188
+ // authoring affordance with no wire representation (concrete dependency UUIDs are per
189
+ // instance, not part of the definition template), so drop non-string entries. Always
190
+ // emit the array — omitting a no-default field diverges the canonical and the chain
191
+ // rejects the whole update (InvalidSignature / decode failure).
192
+ dependencies: (t.dependencies ?? []).filter((d) => typeof d === 'string'),
73
193
  })),
74
194
  };
75
195
  // Copy states (only id and isFinal)
@@ -79,9 +199,20 @@ export function toProtoDefinition(def) {
79
199
  isFinal: state.isFinal,
80
200
  };
81
201
  }
82
- // Pass metadata through unchanged - it's an optional unstructured object
83
- if (def.metadata) {
84
- protoDef.metadata = def.metadata;
202
+ // NOTE: `def.metadata` is the SDK's FiberAppMetadata (name/app/type/version app-routing
203
+ // packaging info), NOT chain metadata. Projecting it onto the wire would make the on-chain
204
+ // canonical + the registry `logicHash` depend on packaging fields (changing `description` would
205
+ // change the signed digest of an otherwise-identical machine), so it is deliberately NOT emitted
206
+ // (the chain's `StateMachineDefinition.metadata` stays absent → `None`). A caller that genuinely
207
+ // needs on-chain metadata sets `ProtoStateMachineDefinition.metadata` explicitly after conversion.
208
+ // Fiber constitution. OMIT the `policy` key entirely for `Unconstrained` (the chain
209
+ // emits nothing for it); emit the bare string `"Immutable"` for `Immutable`; emit a bare
210
+ // object of only the SET dials for `Constrained`. `projectFiberPolicy` returns `undefined`
211
+ // for an (effectively) unconstrained policy, so we assign only when it is a real policy —
212
+ // keeping the wire byte-for-byte identical to the chain's encoding.
213
+ const policy = projectFiberPolicy(def.policy);
214
+ if (policy !== undefined) {
215
+ protoDef.policy = policy;
85
216
  }
86
217
  return protoDef;
87
218
  }