@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.
- package/dist/cjs/apps/compute/index.js +33 -0
- package/dist/cjs/apps/compute/state-machines/compute-rule110.js +164 -0
- package/dist/cjs/apps/compute/state-machines/index.js +9 -0
- package/dist/cjs/apps/contracts/index.js +16 -9
- package/dist/cjs/apps/contracts/state-machines/contract-agreement.js +134 -161
- package/dist/cjs/apps/contracts/state-machines/contract-escrow.js +192 -170
- package/dist/cjs/apps/contracts/state-machines/contract-universal.js +46 -58
- package/dist/cjs/apps/corporate/index.js +2 -2
- package/dist/cjs/apps/corporate/state-machines/corp-board.js +500 -456
- package/dist/cjs/apps/corporate/state-machines/corp-entity.js +487 -361
- package/dist/cjs/apps/corporate/state-machines/corp-securities.js +769 -576
- package/dist/cjs/apps/corporate/state-machines/corp-shareholders.js +567 -557
- package/dist/cjs/apps/governance/index.js +21 -21
- package/dist/cjs/apps/governance/state-machines/dao-multisig.js +188 -209
- package/dist/cjs/apps/governance/state-machines/dao-reputation.js +181 -228
- package/dist/cjs/apps/governance/state-machines/dao-single.js +105 -88
- package/dist/cjs/apps/governance/state-machines/dao-token.js +199 -227
- package/dist/cjs/apps/governance/state-machines/governance-simple.js +231 -231
- package/dist/cjs/apps/governance/state-machines/governance-universal.js +64 -64
- package/dist/cjs/apps/identity/constants.js +55 -22
- package/dist/cjs/apps/identity/index.js +28 -12
- package/dist/cjs/apps/identity/state-machines/identity-agent.js +124 -158
- package/dist/cjs/apps/identity/state-machines/identity-oracle.js +158 -173
- package/dist/cjs/apps/identity/state-machines/identity-registry.js +262 -0
- package/dist/cjs/apps/identity/state-machines/identity-universal.js +51 -57
- package/dist/cjs/apps/identity/state-machines/index.js +3 -1
- package/dist/cjs/apps/index.js +22 -8
- package/dist/cjs/apps/lending/assets.js +247 -0
- package/dist/cjs/apps/lending/credit-scoring.js +87 -0
- package/dist/cjs/apps/lending/eligibility.js +105 -0
- package/dist/cjs/apps/lending/index.js +91 -0
- package/dist/cjs/apps/lending/state-machines/index.js +9 -0
- package/dist/cjs/apps/lending/state-machines/lending-zk-loan.js +433 -0
- package/dist/cjs/apps/markets/index.js +22 -12
- package/dist/cjs/apps/markets/state-machines/market-auction.js +116 -134
- package/dist/cjs/apps/markets/state-machines/market-crowdfund.js +131 -141
- package/dist/cjs/apps/markets/state-machines/market-group-buy.js +163 -184
- package/dist/cjs/apps/markets/state-machines/market-prediction.js +226 -233
- package/dist/cjs/apps/markets/state-machines/market-universal.js +65 -80
- package/dist/cjs/apps/oracles/index.js +3 -3
- package/dist/cjs/apps/privacy/index.js +67 -0
- package/dist/cjs/apps/privacy/state-machines/index.js +17 -0
- package/dist/cjs/apps/privacy/state-machines/mixer-ddhRing.js +286 -0
- package/dist/cjs/apps/privacy/state-machines/note-pool.js +476 -0
- package/dist/cjs/apps/staked-pool/assets.js +103 -0
- package/dist/cjs/apps/staked-pool/base.js +498 -0
- package/dist/cjs/apps/staked-pool/consumer.js +55 -0
- package/dist/cjs/apps/staked-pool/index.js +83 -0
- package/dist/cjs/apps/staked-pool/state-machines/index.js +12 -0
- package/dist/cjs/apps/staked-pool/state-machines/staked-pool-base.js +49 -0
- package/dist/cjs/apps/staked-pool/state-machines/staked-pool-oracle.js +131 -0
- package/dist/cjs/errors.js +3 -3
- package/dist/cjs/generated/google/protobuf/struct.js +5 -5
- package/dist/cjs/generated/google/protobuf/timestamp.js +1 -1
- package/dist/cjs/generated/index.js +11 -7
- package/dist/cjs/generated/openapi.js +6 -0
- package/dist/cjs/generated/ottochain/apps/contracts/v1/contract.js +51 -51
- package/dist/cjs/generated/ottochain/apps/corporate/v1/corporate.js +20 -21
- package/dist/cjs/generated/ottochain/apps/governance/v1/governance.js +14 -14
- package/dist/cjs/generated/ottochain/apps/identity/v1/attestation.js +5 -5
- package/dist/cjs/generated/ottochain/apps/identity/v1/identity.js +125 -131
- package/dist/cjs/generated/ottochain/apps/markets/v1/market.js +108 -108
- package/dist/cjs/generated/ottochain/v1/common.js +5 -5
- package/dist/cjs/generated/ottochain/v1/fiber.js +44 -6
- package/dist/cjs/generated/ottochain/v1/messages.js +1 -1
- package/dist/cjs/generated/ottochain/v1/records.js +1 -1
- package/dist/cjs/index.js +58 -7
- package/dist/cjs/openapi.js +2 -0
- package/dist/cjs/ottochain/drop-nulls.js +1 -2
- package/dist/cjs/ottochain/genesis-manifest.js +17 -11
- package/dist/cjs/ottochain/index.js +23 -13
- package/dist/cjs/ottochain/metagraph-client.js +81 -16
- package/dist/cjs/ottochain/snapshot.js +13 -16
- package/dist/cjs/ottochain/transaction.js +67 -14
- package/dist/cjs/ottochain/types.js +16 -2
- package/dist/cjs/privacy/index.js +14 -0
- package/dist/cjs/privacy/sealed-bid.js +213 -0
- package/dist/cjs/privacy/shield-app.js +131 -0
- package/dist/cjs/schema/effects.js +156 -0
- package/dist/cjs/schema/fiber-app.js +150 -15
- package/dist/cjs/schema/guard-lint.js +343 -0
- package/dist/cjs/schema/guards.js +246 -0
- package/dist/cjs/signing.js +80 -0
- package/dist/cjs/templates/asset-policy.js +190 -0
- package/dist/cjs/templates/index.js +86 -0
- package/dist/cjs/templates/machine.js +130 -0
- package/dist/cjs/templates/migration.js +39 -0
- package/dist/cjs/templates/state-shape.js +38 -0
- package/dist/cjs/types.js +2 -3
- package/dist/cjs/validation.js +9 -11
- package/dist/cjs/verify.js +9 -4
- package/dist/cjs/zk/commit.js +53 -0
- package/dist/cjs/zk/guard.js +107 -0
- package/dist/cjs/zk/index.js +48 -0
- package/dist/cjs/zk/preimage.js +37 -0
- package/dist/cjs/zk/prover.js +87 -0
- package/dist/cjs/zk/registry.js +62 -0
- package/dist/cjs/zk/types.js +28 -0
- package/dist/cjs/zk/witness.js +19 -0
- package/dist/esm/apps/compute/index.js +29 -0
- package/dist/esm/apps/compute/state-machines/compute-rule110.js +161 -0
- package/dist/esm/apps/compute/state-machines/index.js +5 -0
- package/dist/esm/apps/contracts/index.js +9 -5
- package/dist/esm/apps/contracts/state-machines/contract-agreement.js +135 -162
- package/dist/esm/apps/contracts/state-machines/contract-escrow.js +193 -171
- package/dist/esm/apps/contracts/state-machines/contract-universal.js +47 -59
- package/dist/esm/apps/corporate/index.js +2 -2
- package/dist/esm/apps/corporate/state-machines/corp-board.js +501 -457
- package/dist/esm/apps/corporate/state-machines/corp-entity.js +488 -362
- package/dist/esm/apps/corporate/state-machines/corp-securities.js +770 -577
- package/dist/esm/apps/corporate/state-machines/corp-shareholders.js +568 -558
- package/dist/esm/apps/governance/index.js +10 -10
- package/dist/esm/apps/governance/state-machines/dao-multisig.js +189 -210
- package/dist/esm/apps/governance/state-machines/dao-reputation.js +182 -229
- package/dist/esm/apps/governance/state-machines/dao-single.js +106 -89
- package/dist/esm/apps/governance/state-machines/dao-token.js +200 -228
- package/dist/esm/apps/governance/state-machines/governance-simple.js +232 -232
- package/dist/esm/apps/governance/state-machines/governance-universal.js +65 -65
- package/dist/esm/apps/identity/constants.js +52 -21
- package/dist/esm/apps/identity/index.js +14 -9
- package/dist/esm/apps/identity/state-machines/identity-agent.js +125 -159
- package/dist/esm/apps/identity/state-machines/identity-oracle.js +159 -174
- package/dist/esm/apps/identity/state-machines/identity-registry.js +259 -0
- package/dist/esm/apps/identity/state-machines/identity-universal.js +52 -58
- package/dist/esm/apps/identity/state-machines/index.js +1 -0
- package/dist/esm/apps/index.js +9 -5
- package/dist/esm/apps/lending/assets.js +231 -0
- package/dist/esm/apps/lending/credit-scoring.js +81 -0
- package/dist/esm/apps/lending/eligibility.js +99 -0
- package/dist/esm/apps/lending/index.js +69 -0
- package/dist/esm/apps/lending/state-machines/index.js +5 -0
- package/dist/esm/apps/lending/state-machines/lending-zk-loan.js +430 -0
- package/dist/esm/apps/markets/index.js +11 -7
- package/dist/esm/apps/markets/state-machines/market-auction.js +117 -135
- package/dist/esm/apps/markets/state-machines/market-crowdfund.js +132 -142
- package/dist/esm/apps/markets/state-machines/market-group-buy.js +164 -185
- package/dist/esm/apps/markets/state-machines/market-prediction.js +227 -234
- package/dist/esm/apps/markets/state-machines/market-universal.js +66 -81
- package/dist/esm/apps/oracles/index.js +3 -3
- package/dist/esm/apps/privacy/index.js +56 -0
- package/dist/esm/apps/privacy/state-machines/index.js +6 -0
- package/dist/esm/apps/privacy/state-machines/mixer-ddhRing.js +282 -0
- package/dist/esm/apps/privacy/state-machines/note-pool.js +470 -0
- package/dist/esm/apps/staked-pool/assets.js +91 -0
- package/dist/esm/apps/staked-pool/base.js +493 -0
- package/dist/esm/apps/staked-pool/consumer.js +49 -0
- package/dist/esm/apps/staked-pool/index.js +60 -0
- package/dist/esm/apps/staked-pool/state-machines/index.js +6 -0
- package/dist/esm/apps/staked-pool/state-machines/staked-pool-base.js +46 -0
- package/dist/esm/apps/staked-pool/state-machines/staked-pool-oracle.js +127 -0
- package/dist/esm/generated/google/protobuf/struct.js +1 -1
- package/dist/esm/generated/google/protobuf/timestamp.js +1 -1
- package/dist/esm/generated/index.js +9 -5
- package/dist/esm/generated/openapi.js +5 -0
- package/dist/esm/generated/ottochain/apps/contracts/v1/contract.js +47 -47
- package/dist/esm/generated/ottochain/apps/corporate/v1/corporate.js +1 -1
- package/dist/esm/generated/ottochain/apps/governance/v1/governance.js +1 -1
- package/dist/esm/generated/ottochain/apps/identity/v1/attestation.js +1 -1
- package/dist/esm/generated/ottochain/apps/identity/v1/identity.js +115 -121
- package/dist/esm/generated/ottochain/apps/markets/v1/market.js +101 -101
- package/dist/esm/generated/ottochain/v1/common.js +1 -1
- package/dist/esm/generated/ottochain/v1/fiber.js +40 -2
- package/dist/esm/generated/ottochain/v1/messages.js +1 -1
- package/dist/esm/generated/ottochain/v1/records.js +1 -1
- package/dist/esm/index.js +28 -3
- package/dist/esm/openapi.js +1 -0
- package/dist/esm/ottochain/genesis-manifest.js +15 -9
- package/dist/esm/ottochain/index.js +2 -3
- package/dist/esm/ottochain/metagraph-client.js +81 -16
- package/dist/esm/ottochain/snapshot.js +6 -8
- package/dist/esm/ottochain/transaction.js +51 -3
- package/dist/esm/ottochain/types.js +15 -1
- package/dist/esm/privacy/index.js +6 -0
- package/dist/esm/privacy/sealed-bid.js +209 -0
- package/dist/esm/privacy/shield-app.js +127 -0
- package/dist/esm/schema/effects.js +145 -0
- package/dist/esm/schema/fiber-app.js +139 -8
- package/dist/esm/schema/guard-lint.js +337 -0
- package/dist/esm/schema/guards.js +228 -0
- package/dist/esm/signing.js +74 -0
- package/dist/esm/templates/asset-policy.js +182 -0
- package/dist/esm/templates/index.js +41 -0
- package/dist/esm/templates/machine.js +125 -0
- package/dist/esm/templates/migration.js +34 -0
- package/dist/esm/templates/state-shape.js +34 -0
- package/dist/esm/validation.js +1 -3
- package/dist/esm/verify.js +8 -2
- package/dist/esm/zk/commit.js +44 -0
- package/dist/esm/zk/guard.js +99 -0
- package/dist/esm/zk/index.js +19 -0
- package/dist/esm/zk/preimage.js +30 -0
- package/dist/esm/zk/prover.js +82 -0
- package/dist/esm/zk/registry.js +55 -0
- package/dist/esm/zk/types.js +25 -0
- package/dist/esm/zk/witness.js +15 -0
- package/dist/types/apps/compute/index.d.ts +176 -0
- package/dist/types/apps/compute/state-machines/compute-rule110.d.ts +157 -0
- package/dist/types/apps/compute/state-machines/index.d.ts +5 -0
- package/dist/types/apps/contracts/index.d.ts +81 -221
- package/dist/types/apps/contracts/state-machines/contract-agreement.d.ts +23 -98
- package/dist/types/apps/contracts/state-machines/contract-escrow.d.ts +49 -115
- package/dist/types/apps/contracts/state-machines/contract-universal.d.ts +4 -4
- package/dist/types/apps/corporate/index.d.ts +1176 -440
- package/dist/types/apps/corporate/state-machines/corp-board.d.ts +271 -135
- package/dist/types/apps/corporate/state-machines/corp-entity.d.ts +279 -74
- package/dist/types/apps/corporate/state-machines/corp-securities.d.ts +373 -149
- package/dist/types/apps/corporate/state-machines/corp-shareholders.d.ts +252 -80
- package/dist/types/apps/governance/index.d.ts +368 -470
- package/dist/types/apps/governance/state-machines/dao-multisig.d.ts +92 -107
- package/dist/types/apps/governance/state-machines/dao-reputation.d.ts +61 -85
- package/dist/types/apps/governance/state-machines/dao-single.d.ts +25 -47
- package/dist/types/apps/governance/state-machines/dao-token.d.ts +79 -68
- package/dist/types/apps/governance/state-machines/governance-simple.d.ts +95 -125
- package/dist/types/apps/governance/state-machines/governance-universal.d.ts +6 -6
- package/dist/types/apps/identity/constants.d.ts +33 -5
- package/dist/types/apps/identity/index.d.ts +415 -131
- package/dist/types/apps/identity/state-machines/identity-agent.d.ts +23 -23
- package/dist/types/apps/identity/state-machines/identity-oracle.d.ts +27 -98
- package/dist/types/apps/identity/state-machines/identity-registry.d.ts +379 -0
- package/dist/types/apps/identity/state-machines/identity-universal.d.ts +4 -4
- package/dist/types/apps/identity/state-machines/index.d.ts +1 -0
- package/dist/types/apps/index.d.ts +9 -5
- package/dist/types/apps/lending/assets.d.ts +258 -0
- package/dist/types/apps/lending/credit-scoring.d.ts +80 -0
- package/dist/types/apps/lending/eligibility.d.ts +83 -0
- package/dist/types/apps/lending/index.d.ts +556 -0
- package/dist/types/apps/lending/state-machines/index.d.ts +5 -0
- package/dist/types/apps/lending/state-machines/lending-zk-loan.d.ts +536 -0
- package/dist/types/apps/markets/index.d.ts +181 -276
- package/dist/types/apps/markets/state-machines/market-auction.d.ts +25 -49
- package/dist/types/apps/markets/state-machines/market-crowdfund.d.ts +35 -53
- package/dist/types/apps/markets/state-machines/market-group-buy.d.ts +35 -61
- package/dist/types/apps/markets/state-machines/market-prediction.d.ts +65 -86
- package/dist/types/apps/markets/state-machines/market-universal.d.ts +12 -12
- package/dist/types/apps/oracles/index.d.ts +1 -1
- package/dist/types/apps/privacy/index.d.ts +328 -0
- package/dist/types/apps/privacy/state-machines/index.d.ts +6 -0
- package/dist/types/apps/privacy/state-machines/mixer-ddhRing.d.ts +337 -0
- package/dist/types/apps/privacy/state-machines/note-pool.d.ts +196 -0
- package/dist/types/apps/staked-pool/assets.d.ts +53 -0
- package/dist/types/apps/staked-pool/base.d.ts +80 -0
- package/dist/types/apps/staked-pool/consumer.d.ts +29 -0
- package/dist/types/apps/staked-pool/index.d.ts +51 -0
- package/dist/types/apps/staked-pool/state-machines/index.d.ts +6 -0
- package/dist/types/apps/staked-pool/state-machines/staked-pool-base.d.ts +8 -0
- package/dist/types/apps/staked-pool/state-machines/staked-pool-oracle.d.ts +34 -0
- package/dist/types/generated/index.d.ts +5 -5
- package/dist/types/generated/openapi.d.ts +1270 -0
- package/dist/types/generated/ottochain/apps/contracts/v1/contract.d.ts +5 -5
- package/dist/types/generated/ottochain/apps/identity/v1/identity.d.ts +12 -12
- package/dist/types/generated/ottochain/apps/markets/v1/market.d.ts +11 -11
- package/dist/types/generated/ottochain/v1/fiber.d.ts +7 -0
- package/dist/types/index.d.ts +7 -3
- package/dist/types/openapi.d.ts +24 -0
- package/dist/types/ottochain/genesis-manifest.d.ts +11 -5
- package/dist/types/ottochain/index.d.ts +5 -6
- package/dist/types/ottochain/metagraph-client.d.ts +49 -7
- package/dist/types/ottochain/snapshot.d.ts +6 -6
- package/dist/types/ottochain/transaction.d.ts +41 -1
- package/dist/types/ottochain/types.d.ts +336 -31
- package/dist/types/privacy/index.d.ts +6 -0
- package/dist/types/privacy/sealed-bid.d.ts +348 -0
- package/dist/types/privacy/shield-app.d.ts +48 -0
- package/dist/types/schema/effects.d.ts +141 -0
- package/dist/types/schema/fiber-app.d.ts +282 -2
- package/dist/types/schema/guard-lint.d.ts +111 -0
- package/dist/types/schema/guards.d.ts +146 -0
- package/dist/types/signing.d.ts +45 -0
- package/dist/types/templates/asset-policy.d.ts +119 -0
- package/dist/types/templates/index.d.ts +26 -0
- package/dist/types/templates/machine.d.ts +139 -0
- package/dist/types/templates/migration.d.ts +34 -0
- package/dist/types/templates/state-shape.d.ts +30 -0
- package/dist/types/validation.d.ts +22 -217
- package/dist/types/verify.d.ts +4 -0
- package/dist/types/zk/commit.d.ts +28 -0
- package/dist/types/zk/guard.d.ts +46 -0
- package/dist/types/zk/index.d.ts +19 -0
- package/dist/types/zk/preimage.d.ts +10 -0
- package/dist/types/zk/prover.d.ts +34 -0
- package/dist/types/zk/registry.d.ts +34 -0
- package/dist/types/zk/types.d.ts +33 -0
- package/dist/types/zk/witness.d.ts +40 -0
- package/package.json +47 -15
- package/dist/cjs/ottochain/normalize.js +0 -186
- package/dist/esm/ottochain/normalize.js +0 -179
- 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
|
|
72
|
-
|
|
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
|
-
//
|
|
83
|
-
|
|
84
|
-
|
|
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
|
}
|