@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,476 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* shielded-note-pool — a Tornado-style fixed-denomination UTXO-private asset pool.
|
|
4
|
+
*
|
|
5
|
+
* One fiber instance is one shielded pool. The pool's PUBLIC state is the privacy
|
|
6
|
+
* scaffolding only — a Poseidon-Merkle commitment ROOT window, a spent-NULLIFIER set,
|
|
7
|
+
* an append-only output-COMMITMENT log, and the asset-record UUIDs the pool custodies.
|
|
8
|
+
* The real value model is a UTXO note layer that lives OFF-chain in notes committed to
|
|
9
|
+
* the tree; each spend is attested by a single Groth16 proof of the `zk-shielded` circuit.
|
|
10
|
+
*
|
|
11
|
+
* Division of labour (the Kachina/Midnight split — a general verifier in the VM, the
|
|
12
|
+
* shielded pool as ordinary state + transitions on top of it; see
|
|
13
|
+
* docs/design/ergo-patterns-as-fiber-primitives.md §"shielded-note-pool" and
|
|
14
|
+
* docs/design/shielded-transfer-app-sketch.md):
|
|
15
|
+
* - the CIRCUIT proves membership (Poseidon-Merkle inclusion) ∧ authorization
|
|
16
|
+
* (`owner == Poseidon([nsk])`) ∧ nullifier derivation (`nf == Poseidon([rho, nsk])`)
|
|
17
|
+
* ∧ intra-transfer nullifier uniqueness ∧ per-asset conservation ∧ u64 range;
|
|
18
|
+
* - this GUARD (combine) verifies the proof against the pinned `vkey`, binds the
|
|
19
|
+
* public inputs by slicing them from the VERIFIED `publicValues` bytes, rejects an
|
|
20
|
+
* already-spent nullifier (`none`), checks the spend's anchor is still honored
|
|
21
|
+
* (`in [anchor, knownRoots]`), and pins the fee word to a configured value;
|
|
22
|
+
* - the EFFECT (combine) spends the nullifier, logs the output commitment, advances
|
|
23
|
+
* the rolling anchor window, and (on `unshield`) releases exactly one whole
|
|
24
|
+
* `denom`-valued asset record to a clear recipient.
|
|
25
|
+
*
|
|
26
|
+
* It uses NO new metakit opcode. `groth16_verify` verifies the proof; the public-input
|
|
27
|
+
* words are extracted from the verified `publicValues` string with fixed-offset `substr`
|
|
28
|
+
* and re-prefixed `0x` (`{cat:['0x', {substr:[pv,off,64]}]}`) — slicing the verified
|
|
29
|
+
* bytes IS the binding, so no field can be mauled independently of the proof.
|
|
30
|
+
*
|
|
31
|
+
* ──────────────────────────────────────────────────────────────────────────────────────
|
|
32
|
+
* ⚠ UNAUDITED — TEST ASSETS ONLY. The `zk-shielded` circuit and its Groth16 verifier are
|
|
33
|
+
* UNAUDITED; BN254 is ~100-bit security. This MVP is test-assets-only and pins
|
|
34
|
+
* N=1 input / M=1 output / zero fee, with a SINGLE TRUSTED RELAYER for root advancement.
|
|
35
|
+
* Do NOT deploy with value-bearing assets until the circuit + verifier are audited and the
|
|
36
|
+
* in-circuit `newRoot` (which removes the trusted relayer) has landed. See §"Scope" / the
|
|
37
|
+
* Risks list in the design doc.
|
|
38
|
+
* ──────────────────────────────────────────────────────────────────────────────────────
|
|
39
|
+
*
|
|
40
|
+
* MVP constraints (CONFIRMED DEFAULTS):
|
|
41
|
+
* - test assets only;
|
|
42
|
+
* - single trusted relayer gates root advancement (`event.newRoot` is NOT in the proven
|
|
43
|
+
* public values, so a non-relayer could otherwise flood `knownRoots` and evict honest
|
|
44
|
+
* in-flight anchors — a real DoS). LATER: prove `newRoot` in-circuit and drop the relayer.
|
|
45
|
+
* - fixed denomination; the deposit mint is transparent (Tornado-style), the amount is
|
|
46
|
+
* hidden among same-`denom` notes (anonymity set = all live `denom` notes).
|
|
47
|
+
*
|
|
48
|
+
* On-chain primitive facts this builder relies on (re-verified against
|
|
49
|
+
* `@constellation-network/metagraph-sdk-jlvm@1.8.0-rc.5`, see tests/note-pool.test.ts):
|
|
50
|
+
* - array APPEND is `merge([arr,[item]])` (flatten one level); `cat` on arrays ERRORS
|
|
51
|
+
* ("Unexpected input for `cat`") — never use `cat` for array append on-chain;
|
|
52
|
+
* - every crypto/compare value is `0x`-prefixed; an extracted word MUST be re-prefixed
|
|
53
|
+
* `{cat:['0x', {substr:[pv,off,64]}]}` before comparing with a stored `0x` hash;
|
|
54
|
+
* - `none [arr, {===:[{var:""}, x]}]` fires correctly (fresh→true, spent→false);
|
|
55
|
+
* - `groth16_verify` on a garbage bundle returns `false` (graceful deny, never throws);
|
|
56
|
+
* - `pmt_verify([root, leaf, index, [siblings]])` is Poseidon-Merkle inclusion with
|
|
57
|
+
* ROOT-FIRST siblings and a leaf-position `index` (depth range-checked) — exported as
|
|
58
|
+
* {@link pmtMembership} for off-chain witness building / a membership-gated variant.
|
|
59
|
+
*/
|
|
60
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
61
|
+
exports.NOTE_POOL_STATE = exports.ZERO_WORD = exports.pmtMembership = exports.pvField = exports.PV_LAYOUT = void 0;
|
|
62
|
+
exports.notePoolDef = notePoolDef;
|
|
63
|
+
const fiber_app_js_1 = require("../../../schema/fiber-app.js");
|
|
64
|
+
const guards_js_1 = require("../../../schema/guards.js");
|
|
65
|
+
const effects_js_1 = require("../../../schema/effects.js");
|
|
66
|
+
// =============================================================================
|
|
67
|
+
// Public-input layout the guard expects (for fixture / circuit generation)
|
|
68
|
+
// =============================================================================
|
|
69
|
+
/**
|
|
70
|
+
* The EXACT `publicValues` layout the guard slices, for the N=1 input / M=1 output MVP.
|
|
71
|
+
*
|
|
72
|
+
* `publicValues` is the abi-encoded `ShieldedTransferPublicValues` carried as a single
|
|
73
|
+
* `0x`-prefixed lowercase-hex string. Each 32-byte ABI word is 64 hex chars; word `w`
|
|
74
|
+
* begins at hex offset `2 + 64*w` (the leading `2` skips `0x`).
|
|
75
|
+
*
|
|
76
|
+
* `ShieldedTransferPublicValues { bytes32 anchor; bytes32[] nullifiers; bytes32[] outputCms;
|
|
77
|
+
* uint64 fee; bytes32 feeAsset; }`. The circuit commits this via `alloy_sol_types::abi_encode`,
|
|
78
|
+
* which — the struct being a DYNAMIC tuple (it holds the two dynamic arrays) — emits a single leading
|
|
79
|
+
* `0x20` tuple-offset HEAD WORD before the struct body, then the body's own head of array offsets +
|
|
80
|
+
* a tail of (len, elems). For FIXED N=1/M=1 the tail is static and `substr`-addressable.
|
|
81
|
+
*
|
|
82
|
+
* ┌── field ─────────────┬── hex offset ─┬── width ─┬── notes ─────────────────────────────────┐
|
|
83
|
+
* │ tuple head (0x20) │ 2 │ 64 │ abi_encode dynamic-tuple offset; NOT a field│
|
|
84
|
+
* │ anchor │ 66 │ 64 │ Poseidon-Merkle root the inputs prove under │
|
|
85
|
+
* │ nullifiers off (0xa0)│ 130 │ 64 │ body-relative offset of the nullifiers array│
|
|
86
|
+
* │ outputCms off (0xe0)│ 194 │ 64 │ body-relative offset of the outputCms array │
|
|
87
|
+
* │ fee (uint64 word) │ 258 │ 64 │ transparent fee, right-aligned in the word │
|
|
88
|
+
* │ feeAsset │ 322 │ 64 │ asset-as-Fr the fee is denominated in │
|
|
89
|
+
* │ nullifiers.len │ 386 │ 64 │ == 1 for the N=1 MVP │
|
|
90
|
+
* │ nullifiers[0] │ 450 │ 64 │ the revealed input nullifier │
|
|
91
|
+
* │ outputCms.len │ 514 │ 64 │ == 1 for the M=1 MVP │
|
|
92
|
+
* │ outputCms[0] │ 578 │ 64 │ the revealed output commitment │
|
|
93
|
+
* └──────────────────────┴───────────────┴──────────┴─────────────────────────────────────────────┘
|
|
94
|
+
*
|
|
95
|
+
* The word ORDER and ENCODING a matching SP1 fixture MUST produce (so the placeholder can be
|
|
96
|
+
* swapped for a real proof): the `0x`-string is
|
|
97
|
+
* 0x ‖ 0x20 ‖ anchor ‖ nullifiers.off ‖ outputCms.off ‖ fee ‖ feeAsset ‖
|
|
98
|
+
* nullifiers.len ‖ nullifiers[0] ‖ outputCms.len ‖ outputCms[0]
|
|
99
|
+
* laid out by the circuit's `commit_slice(abi_encode(ShieldedTransferPublicValues{..}))`, such that
|
|
100
|
+
* the five field offsets below land on the words above. Every word is a lowercase 32-byte hex with
|
|
101
|
+
* NO `0x` per-word prefix (the single `0x` is on the whole string).
|
|
102
|
+
*
|
|
103
|
+
* RECONCILED 2026-06 against the REAL `zk-shielded` circuit (~/repos/metakit-sdk/rust/zk-shielded):
|
|
104
|
+
* an earlier version of this layout omitted the leading `0x20` dynamic-tuple head word, so every
|
|
105
|
+
* offset was one 32-byte word (64 hex) too low and the guard sliced the WRONG words. The circuit is
|
|
106
|
+
* the source of truth; the offsets above were corrected (+64 each) to match a real SP1 Groth16 proof
|
|
107
|
+
* whose `publicValues` is `0x ‖ 0x20 ‖ anchor ‖ 0xa0 ‖ 0xe0 ‖ fee ‖ feeAsset ‖ 1 ‖ nf ‖ 1 ‖ cm`.
|
|
108
|
+
*
|
|
109
|
+
* cm / nf preimages (the circuit's, fixed and byte-for-byte across Scala/Rust/TS):
|
|
110
|
+
* - `cm = Poseidon([value_as_fr, owner, asset, rho])` (4-input, MAX poseidon arity);
|
|
111
|
+
* - `owner = Poseidon([nsk])`;
|
|
112
|
+
* - `nf = Poseidon([rho, nsk])` (FIELD ORDER rho, nsk).
|
|
113
|
+
*/
|
|
114
|
+
exports.PV_LAYOUT = {
|
|
115
|
+
/** anchor — word 1 (word 0 is the dynamic-tuple `0x20` head word; see the table). */
|
|
116
|
+
anchor: 66,
|
|
117
|
+
/** fee — word 4 (uint64 right-aligned). MVP pins this whole word to {@link NotePoolOptions.feeWord}. */
|
|
118
|
+
fee: 258,
|
|
119
|
+
/** feeAsset — word 5. */
|
|
120
|
+
feeAsset: 322,
|
|
121
|
+
/** nullifiers[0] — after the nullifiers length word @386. */
|
|
122
|
+
nullifier: 450,
|
|
123
|
+
/** outputCms[0] — after the outputCms length word @514. */
|
|
124
|
+
outputCm: 578,
|
|
125
|
+
};
|
|
126
|
+
// =============================================================================
|
|
127
|
+
// Field extraction — slice the VERIFIED bytes, re-prefix 0x (the binding)
|
|
128
|
+
// =============================================================================
|
|
129
|
+
const WORD_HEX = 64; // a 32-byte ABI word as hex chars
|
|
130
|
+
/**
|
|
131
|
+
* Lift `publicValues` word at hex `offset` back to a `0x`-hex value comparable with a stored
|
|
132
|
+
* `bytes32`/`hash`. `cat` of two STRINGS is valid on-chain; `cat` of arrays ERRORS — this is
|
|
133
|
+
* strings only. The slice is taken from the SAME bytes `groth16_verify` consumed, so a changed
|
|
134
|
+
* field invalidates the proof: re-prefixing the verified slice IS the public-input binding.
|
|
135
|
+
*/
|
|
136
|
+
const pvField = (offset) => ({
|
|
137
|
+
cat: ['0x', { substr: [{ var: 'event.publicValues' }, offset, WORD_HEX] }],
|
|
138
|
+
});
|
|
139
|
+
exports.pvField = pvField;
|
|
140
|
+
/**
|
|
141
|
+
* `pmt_verify([root, leaf, index, [siblings]])` Poseidon-Merkle inclusion (root-first siblings,
|
|
142
|
+
* leaf-position `index`, depth = `siblings.length`, range-checked). Exported for off-chain witness
|
|
143
|
+
* building and for a membership-gated pool variant. NOTE: the MVP `transfer`/`unshield` guards do
|
|
144
|
+
* NOT call `pmt_verify` — membership is proven INSIDE the circuit (`verify_inclusion`) and bound to
|
|
145
|
+
* the verified `anchor`; the chain only checks `anchor ∈ knownRoots`. This helper exists so a
|
|
146
|
+
* downstream pool that wants an additional ON-CHAIN inclusion check (e.g. for a transparent leaf)
|
|
147
|
+
* can express it with the verified operand format.
|
|
148
|
+
*/
|
|
149
|
+
const pmtMembership = (rootVar, leafVar, indexVar, siblingsVar) => ({ pmt_verify: [rootVar, leafVar, indexVar, siblingsVar] });
|
|
150
|
+
exports.pmtMembership = pmtMembership;
|
|
151
|
+
/** The all-zero 32-byte word — the MVP `feeWord` (pins fee=0). */
|
|
152
|
+
exports.ZERO_WORD = '0x' + '0'.repeat(64);
|
|
153
|
+
/** Public state every shielded note-pool carries (the note value model itself is private/off-chain). */
|
|
154
|
+
exports.NOTE_POOL_STATE = {
|
|
155
|
+
vkey: {
|
|
156
|
+
type: 'hash',
|
|
157
|
+
immutable: true,
|
|
158
|
+
description: 'zk-shielded program vkey (32B, 0x)',
|
|
159
|
+
},
|
|
160
|
+
depth: {
|
|
161
|
+
type: 'integer',
|
|
162
|
+
immutable: true,
|
|
163
|
+
description: 'merkle depth pinned at creation',
|
|
164
|
+
},
|
|
165
|
+
denom: {
|
|
166
|
+
type: 'integer',
|
|
167
|
+
immutable: true,
|
|
168
|
+
description: 'fixed note denomination (asset units)',
|
|
169
|
+
},
|
|
170
|
+
poolPolicyRef: {
|
|
171
|
+
type: 'string',
|
|
172
|
+
immutable: true,
|
|
173
|
+
description: 'asset policy the pool mints/burns note-records under',
|
|
174
|
+
},
|
|
175
|
+
feeAsset: {
|
|
176
|
+
type: 'hash',
|
|
177
|
+
immutable: true,
|
|
178
|
+
description: '0x Fr label fees are charged in (== asset-as-Fr)',
|
|
179
|
+
},
|
|
180
|
+
feeWord: {
|
|
181
|
+
type: 'hash',
|
|
182
|
+
immutable: true,
|
|
183
|
+
description: 'the EXACT 0x 32-byte word `fee` must equal (MVP: zero word)',
|
|
184
|
+
},
|
|
185
|
+
relayer: {
|
|
186
|
+
type: 'string',
|
|
187
|
+
immutable: true,
|
|
188
|
+
description: 'DAG address authorized to advance the root (MVP single trusted relayer)',
|
|
189
|
+
},
|
|
190
|
+
rootWindow: { type: 'integer', immutable: true, default: 64 },
|
|
191
|
+
currentRoot: { type: 'hash', computed: true },
|
|
192
|
+
knownRoots: {
|
|
193
|
+
type: 'array',
|
|
194
|
+
computed: true,
|
|
195
|
+
description: 'rolling window of valid anchors (0x)',
|
|
196
|
+
},
|
|
197
|
+
nullifiers: {
|
|
198
|
+
type: 'array',
|
|
199
|
+
computed: true,
|
|
200
|
+
description: 'spent set (0x); monotonic — O(n) `none` scan, see ceiling note',
|
|
201
|
+
},
|
|
202
|
+
commitments: {
|
|
203
|
+
type: 'array',
|
|
204
|
+
computed: true,
|
|
205
|
+
description: 'append-only output-commitment log (0x)',
|
|
206
|
+
},
|
|
207
|
+
noteRecords: {
|
|
208
|
+
type: 'array',
|
|
209
|
+
computed: true,
|
|
210
|
+
description: 'assetId UUIDs of live note-records the pool holds',
|
|
211
|
+
},
|
|
212
|
+
leafCount: { type: 'integer', computed: true, default: 0 },
|
|
213
|
+
transfers: { type: 'integer', computed: true, default: 0 },
|
|
214
|
+
};
|
|
215
|
+
// =============================================================================
|
|
216
|
+
// Guard / effect builders
|
|
217
|
+
// =============================================================================
|
|
218
|
+
/** Extracted, 0x-re-prefixed public-input words (shared by `transfer` and `unshield`). */
|
|
219
|
+
const pvWords = () => ({
|
|
220
|
+
anchor: (0, exports.pvField)(exports.PV_LAYOUT.anchor),
|
|
221
|
+
feeWord: (0, exports.pvField)(exports.PV_LAYOUT.fee),
|
|
222
|
+
feeAsset: (0, exports.pvField)(exports.PV_LAYOUT.feeAsset),
|
|
223
|
+
nullifier: (0, exports.pvField)(exports.PV_LAYOUT.nullifier),
|
|
224
|
+
newCm: (0, exports.pvField)(exports.PV_LAYOUT.outputCm),
|
|
225
|
+
});
|
|
226
|
+
/**
|
|
227
|
+
* The proof + nullifier + anchor + fee binding shared by every spend (combiner-only, all
|
|
228
|
+
* stateful). Binds against the EXACT verified bytes: any field change invalidates the Groth16.
|
|
229
|
+
*/
|
|
230
|
+
const spendBinding = (w) => [
|
|
231
|
+
// 1. the proof verifies against the pool's pinned vkey over EXACTLY these public bytes
|
|
232
|
+
{
|
|
233
|
+
groth16_verify: [{ var: 'state.vkey' }, { var: 'event.publicValues' }, { var: 'event.proof' }],
|
|
234
|
+
},
|
|
235
|
+
// 2. the spend's anchor is a root we produced and still honor
|
|
236
|
+
{ in: [w.anchor, { var: 'state.knownRoots' }] },
|
|
237
|
+
// 3. INTER-transfer double-spend: the (0x-prefixed) nullifier is not already spent
|
|
238
|
+
{
|
|
239
|
+
none: [{ var: 'state.nullifiers' }, { '===': [{ var: '' }, w.nullifier] }],
|
|
240
|
+
},
|
|
241
|
+
// 4. no fee-asset spoofing
|
|
242
|
+
{ '===': [w.feeAsset, { var: 'state.feeAsset' }] },
|
|
243
|
+
// 5. no value siphon via fee: the whole fee word is pinned (MVP: the zero word ⇒ fee==0)
|
|
244
|
+
{ '===': [w.feeWord, { var: 'state.feeWord' }] },
|
|
245
|
+
];
|
|
246
|
+
/**
|
|
247
|
+
* Build the shielded-note-pool fiber app.
|
|
248
|
+
*
|
|
249
|
+
* Single state `ACTIVE → ACTIVE` with three transitions:
|
|
250
|
+
* - `transfer` — note-to-note spend (no public asset move); advances the tree. Relayer-gated.
|
|
251
|
+
* - `noteMinted`— witness transition recording a deposit's commitment + record UUID (the deposit
|
|
252
|
+
* itself is an asset-model `MintAsset` into `Fiber(poolId)`, gated by the
|
|
253
|
+
* `poolPolicyRef` mintPolicy — NOT a fiber transition).
|
|
254
|
+
* - `unshield` — burn a note (nullify), release one whole `denom` note-record to a clear recipient.
|
|
255
|
+
* Self-sufficient because it is CASCADE-REACHABLE (asset transfers fire from cascades).
|
|
256
|
+
*/
|
|
257
|
+
function notePoolDef(opts) {
|
|
258
|
+
const feeWord = opts.feeWord ?? exports.ZERO_WORD;
|
|
259
|
+
const w = pvWords();
|
|
260
|
+
// --- transfer: note-to-note spend, advance the rolling anchor window ---------------------
|
|
261
|
+
const transferGuard = {
|
|
262
|
+
and: [
|
|
263
|
+
...spendBinding(w),
|
|
264
|
+
// Root-advance authz: only the pinned relayer's signed `transfer` advances the tree, so a
|
|
265
|
+
// non-relayer cannot flood `knownRoots` and evict honest in-flight anchors (DoS). Uses
|
|
266
|
+
// `proofs[].address` (verified signers) — NOT a forgeable `event.*` field.
|
|
267
|
+
(0, guards_js_1.signerIsParty)('state.relayer'),
|
|
268
|
+
],
|
|
269
|
+
};
|
|
270
|
+
const transferEffect = {
|
|
271
|
+
merge: [
|
|
272
|
+
{ var: 'state' },
|
|
273
|
+
{
|
|
274
|
+
// append via merge (NOT cat — cat errors on arrays on-chain)
|
|
275
|
+
nullifiers: { merge: [{ var: 'state.nullifiers' }, [w.nullifier]] },
|
|
276
|
+
commitments: { merge: [{ var: 'state.commitments' }, [w.newCm]] },
|
|
277
|
+
currentRoot: { var: 'event.newRoot' },
|
|
278
|
+
// append newRoot, then trim to the last rootWindow anchors via negative-start slice
|
|
279
|
+
knownRoots: {
|
|
280
|
+
slice: [
|
|
281
|
+
{
|
|
282
|
+
merge: [{ var: 'state.knownRoots' }, [{ var: 'event.newRoot' }]],
|
|
283
|
+
},
|
|
284
|
+
{ '*': [-1, { var: 'state.rootWindow' }] },
|
|
285
|
+
],
|
|
286
|
+
},
|
|
287
|
+
leafCount: { '+': [{ var: 'state.leafCount' }, 1] },
|
|
288
|
+
transfers: { '+': [{ var: 'state.transfers' }, 1] },
|
|
289
|
+
},
|
|
290
|
+
],
|
|
291
|
+
};
|
|
292
|
+
// --- noteMinted: witness a deposit (record its commitment + record UUID) ------------------
|
|
293
|
+
// The deposit is an asset-model MintAsset of a `denom`-valued record into Fiber(poolId), gated by
|
|
294
|
+
// the poolPolicyRef mintPolicy (pins amount==denom, holder==pool, depositor-signed). This witness
|
|
295
|
+
// transition only records bookkeeping; `unshield` independently re-checks record custody at
|
|
296
|
+
// withdrawal (the asset combiner's R1 holder defense), so a forged noteMinted cannot extract value.
|
|
297
|
+
const noteMintedGuard = {
|
|
298
|
+
// the depositor (who signed the mint) signs this witness; the commitment + recordId are theirs.
|
|
299
|
+
// No balance read (no guard can witness an escrow). The release-time custody check is the real gate.
|
|
300
|
+
and: [(0, guards_js_1.signerIsParty)('event.depositor')],
|
|
301
|
+
};
|
|
302
|
+
const noteMintedEffect = {
|
|
303
|
+
merge: [
|
|
304
|
+
{ var: 'state' },
|
|
305
|
+
{
|
|
306
|
+
commitments: {
|
|
307
|
+
merge: [{ var: 'state.commitments' }, [{ var: 'event.commitment' }]],
|
|
308
|
+
},
|
|
309
|
+
noteRecords: {
|
|
310
|
+
merge: [{ var: 'state.noteRecords' }, [{ var: 'event.recordId' }]],
|
|
311
|
+
},
|
|
312
|
+
leafCount: { '+': [{ var: 'state.leafCount' }, 1] },
|
|
313
|
+
},
|
|
314
|
+
],
|
|
315
|
+
};
|
|
316
|
+
// --- unshield: burn a note, release exactly one whole note-record ------------------------
|
|
317
|
+
const unshieldGuard = {
|
|
318
|
+
and: [
|
|
319
|
+
...spendBinding(w),
|
|
320
|
+
// can only release a record the pool actually holds (combiner R1 holder defense re-checks too)
|
|
321
|
+
{ in: [{ var: 'event.recordId' }, { var: 'state.noteRecords' }] },
|
|
322
|
+
],
|
|
323
|
+
};
|
|
324
|
+
const unshieldEffect = {
|
|
325
|
+
merge: [
|
|
326
|
+
{ var: 'state' },
|
|
327
|
+
{
|
|
328
|
+
nullifiers: { merge: [{ var: 'state.nullifiers' }, [w.nullifier]] },
|
|
329
|
+
// remove the released record id from the live set
|
|
330
|
+
noteRecords: {
|
|
331
|
+
filter: [{ var: 'state.noteRecords' }, { '!==': [{ var: '' }, { var: 'event.recordId' }] }],
|
|
332
|
+
},
|
|
333
|
+
transfers: { '+': [{ var: 'state.transfers' }, 1] },
|
|
334
|
+
// release exactly one whole denom-valued record to a clear recipient wallet
|
|
335
|
+
...(0, effects_js_1.transferAsset)([
|
|
336
|
+
{
|
|
337
|
+
assetId: { var: 'event.recordId' },
|
|
338
|
+
recipient: (0, effects_js_1.toWallet)({ var: 'event.recipient' }),
|
|
339
|
+
},
|
|
340
|
+
]),
|
|
341
|
+
},
|
|
342
|
+
],
|
|
343
|
+
};
|
|
344
|
+
return (0, fiber_app_js_1.defineFiberApp)({
|
|
345
|
+
metadata: {
|
|
346
|
+
name: 'ShieldedNotePool',
|
|
347
|
+
app: 'privacy',
|
|
348
|
+
type: 'shielded-note-pool',
|
|
349
|
+
version: '0.1.0',
|
|
350
|
+
description: 'UNAUDITED, TEST-ASSETS-ONLY fixed-denomination UTXO-private asset pool over the zk-shielded ' +
|
|
351
|
+
'Groth16 circuit (BN254 ~100-bit). Notes live off-chain in a Poseidon-Merkle tree; spends are ' +
|
|
352
|
+
'attested by a Groth16 proof. Public state = nullifier set + anchor window + commitment log. ' +
|
|
353
|
+
'Single trusted relayer advances the root (MVP). Do NOT deploy with value-bearing assets.',
|
|
354
|
+
},
|
|
355
|
+
createSchema: {
|
|
356
|
+
required: ['vkey', 'depth', 'denom', 'poolPolicyRef', 'feeAsset', 'relayer'],
|
|
357
|
+
properties: {
|
|
358
|
+
vkey: { type: 'hash', immutable: true, default: opts.vkey },
|
|
359
|
+
depth: { type: 'integer', immutable: true, default: opts.depth },
|
|
360
|
+
denom: { type: 'integer', immutable: true, default: opts.denom },
|
|
361
|
+
poolPolicyRef: {
|
|
362
|
+
type: 'string',
|
|
363
|
+
immutable: true,
|
|
364
|
+
default: opts.poolPolicyRef,
|
|
365
|
+
},
|
|
366
|
+
feeAsset: { type: 'hash', immutable: true, default: opts.feeAsset },
|
|
367
|
+
feeWord: { type: 'hash', immutable: true, default: feeWord },
|
|
368
|
+
relayer: { type: 'string', immutable: true, default: opts.relayer },
|
|
369
|
+
rootWindow: {
|
|
370
|
+
type: 'integer',
|
|
371
|
+
immutable: true,
|
|
372
|
+
default: opts.rootWindow ?? 64,
|
|
373
|
+
},
|
|
374
|
+
},
|
|
375
|
+
},
|
|
376
|
+
stateSchema: { properties: { ...exports.NOTE_POOL_STATE } },
|
|
377
|
+
eventSchemas: {
|
|
378
|
+
transfer: {
|
|
379
|
+
description: 'Note-to-note shielded spend (N=1/M=1), attested by a zk-shielded Groth16 proof; advances the tree.',
|
|
380
|
+
required: ['proof', 'publicValues', 'newRoot'],
|
|
381
|
+
properties: {
|
|
382
|
+
proof: {
|
|
383
|
+
type: 'string',
|
|
384
|
+
description: 'Groth16 proof bytes (0x hex)',
|
|
385
|
+
},
|
|
386
|
+
publicValues: {
|
|
387
|
+
type: 'string',
|
|
388
|
+
description: 'abi-encoded ShieldedTransferPublicValues (0x hex); see PV_LAYOUT',
|
|
389
|
+
},
|
|
390
|
+
newRoot: {
|
|
391
|
+
type: 'hash',
|
|
392
|
+
description: 'wallet/relayer-computed root after appending outputCms[0]',
|
|
393
|
+
},
|
|
394
|
+
},
|
|
395
|
+
},
|
|
396
|
+
noteMinted: {
|
|
397
|
+
description: "Witness a deposit: record its commitment + the minted note-record's UUID.",
|
|
398
|
+
required: ['commitment', 'recordId', 'depositor'],
|
|
399
|
+
properties: {
|
|
400
|
+
commitment: {
|
|
401
|
+
type: 'hash',
|
|
402
|
+
description: 'client-computed cm = Poseidon([denom, owner, feeAsset, rho]) (0x)',
|
|
403
|
+
},
|
|
404
|
+
recordId: {
|
|
405
|
+
type: 'uuid',
|
|
406
|
+
description: 'assetId of the denom-valued record minted into Fiber(poolId)',
|
|
407
|
+
},
|
|
408
|
+
depositor: {
|
|
409
|
+
type: 'address',
|
|
410
|
+
description: 'DAG address of the depositor who signed the mint',
|
|
411
|
+
},
|
|
412
|
+
},
|
|
413
|
+
},
|
|
414
|
+
unshield: {
|
|
415
|
+
description: 'Burn a note, release one whole denom-valued note-record to a clear recipient.',
|
|
416
|
+
required: ['proof', 'publicValues', 'recordId', 'recipient'],
|
|
417
|
+
properties: {
|
|
418
|
+
proof: {
|
|
419
|
+
type: 'string',
|
|
420
|
+
description: 'Groth16 proof bytes (0x hex)',
|
|
421
|
+
},
|
|
422
|
+
publicValues: {
|
|
423
|
+
type: 'string',
|
|
424
|
+
description: 'abi-encoded ShieldedTransferPublicValues (0x hex); see PV_LAYOUT',
|
|
425
|
+
},
|
|
426
|
+
recordId: {
|
|
427
|
+
type: 'uuid',
|
|
428
|
+
description: 'note-record to release; MUST be in state.noteRecords',
|
|
429
|
+
},
|
|
430
|
+
recipient: {
|
|
431
|
+
type: 'address',
|
|
432
|
+
description: 'clear DAG address that receives the released record',
|
|
433
|
+
},
|
|
434
|
+
},
|
|
435
|
+
},
|
|
436
|
+
},
|
|
437
|
+
states: {
|
|
438
|
+
ACTIVE: {
|
|
439
|
+
id: 'ACTIVE',
|
|
440
|
+
isFinal: false,
|
|
441
|
+
metadata: {
|
|
442
|
+
label: 'Active',
|
|
443
|
+
description: 'Pool accepts shielded transfers, deposits, and withdrawals',
|
|
444
|
+
category: 'active',
|
|
445
|
+
},
|
|
446
|
+
},
|
|
447
|
+
},
|
|
448
|
+
initialState: 'ACTIVE',
|
|
449
|
+
transitions: [
|
|
450
|
+
{
|
|
451
|
+
from: 'ACTIVE',
|
|
452
|
+
to: 'ACTIVE',
|
|
453
|
+
eventName: 'transfer',
|
|
454
|
+
guard: transferGuard,
|
|
455
|
+
effect: transferEffect,
|
|
456
|
+
dependencies: [],
|
|
457
|
+
},
|
|
458
|
+
{
|
|
459
|
+
from: 'ACTIVE',
|
|
460
|
+
to: 'ACTIVE',
|
|
461
|
+
eventName: 'noteMinted',
|
|
462
|
+
guard: noteMintedGuard,
|
|
463
|
+
effect: noteMintedEffect,
|
|
464
|
+
dependencies: [],
|
|
465
|
+
},
|
|
466
|
+
{
|
|
467
|
+
from: 'ACTIVE',
|
|
468
|
+
to: 'ACTIVE',
|
|
469
|
+
eventName: 'unshield',
|
|
470
|
+
guard: unshieldGuard,
|
|
471
|
+
effect: unshieldEffect,
|
|
472
|
+
dependencies: [],
|
|
473
|
+
},
|
|
474
|
+
],
|
|
475
|
+
});
|
|
476
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Asset-subsystem integration for the staked-pool family.
|
|
4
|
+
*
|
|
5
|
+
* Two asset roles:
|
|
6
|
+
* - STAKE token: a governed fungible. Joining is a custody `Transfer` of the whole stake instance into
|
|
7
|
+
* `AssetHolder.Fiber(poolId)` (the loan family's "lock = Transfer into Fiber holder" pattern); the
|
|
8
|
+
* pool's `stake_and_join` guard verifies the custody via `heldAssets` (H5). Withdraw/slash move it back
|
|
9
|
+
* out via the fiber's `_transferAsset` directive.
|
|
10
|
+
* - REWARD token: a shared fungible the pool pre-holds. `claim_reward` moves ONE whole reward instance to
|
|
11
|
+
* a verified in-consensus claimant (per-claim model — the whole-asset transfer has no amount field).
|
|
12
|
+
*
|
|
13
|
+
* Reuses the lending family's asset payload builders (`createAssetPolicyPayload`, `createMintAssetPayload`,
|
|
14
|
+
* `createApplyMorphismPayload`, `fiberHolder`, `walletHolder`) — re-exported here so a staked-pool caller
|
|
15
|
+
* has a single import surface.
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.TokenBehaviors = exports.walletHolder = exports.fiberHolder = exports.createApplyMorphismPayload = exports.createMintAssetPayload = exports.createAssetPolicyPayload = void 0;
|
|
19
|
+
exports.stakePolicy = stakePolicy;
|
|
20
|
+
exports.rewardPotPolicy = rewardPotPolicy;
|
|
21
|
+
exports.stakeJoinOp = stakeJoinOp;
|
|
22
|
+
exports.mintRewardInstancesOp = mintRewardInstancesOp;
|
|
23
|
+
const assets_js_1 = require("../lending/assets.js");
|
|
24
|
+
Object.defineProperty(exports, "createAssetPolicyPayload", { enumerable: true, get: function () { return assets_js_1.createAssetPolicyPayload; } });
|
|
25
|
+
Object.defineProperty(exports, "createMintAssetPayload", { enumerable: true, get: function () { return assets_js_1.createMintAssetPayload; } });
|
|
26
|
+
Object.defineProperty(exports, "createApplyMorphismPayload", { enumerable: true, get: function () { return assets_js_1.createApplyMorphismPayload; } });
|
|
27
|
+
Object.defineProperty(exports, "fiberHolder", { enumerable: true, get: function () { return assets_js_1.fiberHolder; } });
|
|
28
|
+
Object.defineProperty(exports, "walletHolder", { enumerable: true, get: function () { return assets_js_1.walletHolder; } });
|
|
29
|
+
Object.defineProperty(exports, "TokenBehaviors", { enumerable: true, get: function () { return assets_js_1.TokenBehaviors; } });
|
|
30
|
+
/**
|
|
31
|
+
* Stake-token policy: a governed fungible. `Transfer` is the custody move into/out of the pool fiber.
|
|
32
|
+
* Transferable so withdraw/slash can return it (a soulbound stake would fail the R1 transferable check
|
|
33
|
+
* on withdraw — see design §11; not the default here).
|
|
34
|
+
*/
|
|
35
|
+
function stakePolicy(name = 'staked-pool-stake-v1.asset', version = '1.0.0') {
|
|
36
|
+
return {
|
|
37
|
+
name,
|
|
38
|
+
version,
|
|
39
|
+
behavior: assets_js_1.TokenBehaviors.GovernedFungible,
|
|
40
|
+
supply: {
|
|
41
|
+
maxSupply: null,
|
|
42
|
+
mintPolicy: null,
|
|
43
|
+
// Only the holder may burn their own stake (defensive; the pool moves it via Transfer, not Burn).
|
|
44
|
+
burnPolicy: { in: [{ var: 'holder.Wallet.address' }, { var: 'signers' }] },
|
|
45
|
+
decimals: 0,
|
|
46
|
+
},
|
|
47
|
+
morphisms: {
|
|
48
|
+
// Custody Transfer is the join/withdraw mechanism; gated so the pool fiber authorizes movement.
|
|
49
|
+
Transfer: { visibility: 'Public' },
|
|
50
|
+
Burn: { visibility: 'Public' },
|
|
51
|
+
},
|
|
52
|
+
stateShape: {},
|
|
53
|
+
metadata: { family: 'staked-pool', role: 'stake' },
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Reward-pot policy: a shared fungible the pool pre-holds and pays out one whole instance per claim.
|
|
58
|
+
* `mintGuard` (optional) gates who may mint reward instances into the pool (e.g. the pool authority);
|
|
59
|
+
* omit for an open mint pinned operationally.
|
|
60
|
+
*/
|
|
61
|
+
function rewardPotPolicy(mintGuard = null, name = 'staked-pool-reward-v1.asset', version = '1.0.0') {
|
|
62
|
+
return {
|
|
63
|
+
name,
|
|
64
|
+
version,
|
|
65
|
+
behavior: assets_js_1.TokenBehaviors.Fungible,
|
|
66
|
+
supply: {
|
|
67
|
+
maxSupply: null,
|
|
68
|
+
mintPolicy: mintGuard,
|
|
69
|
+
burnPolicy: null,
|
|
70
|
+
decimals: 0,
|
|
71
|
+
},
|
|
72
|
+
morphisms: {
|
|
73
|
+
Transfer: { visibility: 'Public' },
|
|
74
|
+
},
|
|
75
|
+
stateShape: {},
|
|
76
|
+
metadata: { family: 'staked-pool', role: 'reward' },
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* stake_and_join driver: the participant Transfers their whole stake instance into the pool fiber BEFORE
|
|
81
|
+
* the `stake_and_join` event (custody = Transfer to `AssetHolder.Fiber`). Mirrors `lockCollateralOp`.
|
|
82
|
+
*/
|
|
83
|
+
function stakeJoinOp(args) {
|
|
84
|
+
return (0, assets_js_1.createApplyMorphismPayload)({
|
|
85
|
+
assetId: args.stakeAssetId,
|
|
86
|
+
kind: 'Transfer',
|
|
87
|
+
recipient: (0, assets_js_1.fiberHolder)(args.poolFiberId),
|
|
88
|
+
targetSequenceNumber: args.targetSequenceNumber,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Pre-mint reward instances into the pool fiber (sized to expected claimants for the epoch). Mirrors
|
|
93
|
+
* `mintPrincipalOp` but mints to `Fiber(poolId)` so `claim_reward` can later transfer one whole instance.
|
|
94
|
+
*/
|
|
95
|
+
function mintRewardInstancesOp(args) {
|
|
96
|
+
return (0, assets_js_1.createMintAssetPayload)({
|
|
97
|
+
assetId: args.rewardAssetId,
|
|
98
|
+
policyRef: args.rewardPolicyRef,
|
|
99
|
+
holder: (0, assets_js_1.fiberHolder)(args.poolFiberId),
|
|
100
|
+
amount: args.amount,
|
|
101
|
+
...(args.witness ? { witness: args.witness } : {}),
|
|
102
|
+
});
|
|
103
|
+
}
|