zklicensing 0.1.0-beta.2 → 0.1.0-beta.21
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/README.md +417 -201
- package/build/agent.d.ts +371 -0
- package/build/agent.d.ts.map +1 -0
- package/build/agent.js +553 -0
- package/build/agent.js.map +1 -0
- package/build/agentActions.d.ts +841 -0
- package/build/agentActions.d.ts.map +1 -0
- package/build/agentActions.js +581 -0
- package/build/agentActions.js.map +1 -0
- package/build/agentRecord.d.ts +83 -0
- package/build/agentRecord.d.ts.map +1 -0
- package/build/agentRecord.js +69 -0
- package/build/agentRecord.js.map +1 -0
- package/build/agentVendor.d.ts +220 -0
- package/build/agentVendor.d.ts.map +1 -0
- package/build/agentVendor.js +306 -0
- package/build/agentVendor.js.map +1 -0
- package/build/appsLookup.d.ts +14 -0
- package/build/appsLookup.d.ts.map +1 -0
- package/build/appsLookup.js +12 -0
- package/build/appsLookup.js.map +1 -0
- package/build/archiveBootstrap.d.ts +31 -5
- package/build/archiveBootstrap.d.ts.map +1 -0
- package/build/archiveBootstrap.js +140 -47
- package/build/archiveBootstrap.js.map +1 -0
- package/build/atomicJson.d.ts +5 -0
- package/build/atomicJson.d.ts.map +1 -0
- package/build/atomicJson.js +55 -0
- package/build/atomicJson.js.map +1 -0
- package/build/bindClient.d.ts +85 -0
- package/build/bindClient.d.ts.map +1 -0
- package/build/bindClient.js +187 -0
- package/build/bindClient.js.map +1 -0
- package/build/buyClient.d.ts +27 -4
- package/build/buyClient.d.ts.map +1 -0
- package/build/buyClient.js +72 -26
- package/build/buyClient.js.map +1 -0
- package/build/chainHead.d.ts +61 -0
- package/build/chainHead.d.ts.map +1 -0
- package/build/chainHead.js +88 -0
- package/build/chainHead.js.map +1 -0
- package/build/compactMerkleMap.d.ts +72 -0
- package/build/compactMerkleMap.d.ts.map +1 -0
- package/build/compactMerkleMap.js +224 -0
- package/build/compactMerkleMap.js.map +1 -0
- package/build/contractInterface.d.ts +191 -51
- package/build/contractInterface.d.ts.map +1 -0
- package/build/contractInterface.js +234 -43
- package/build/contractInterface.js.map +1 -0
- package/build/contractTypes.d.ts +9 -0
- package/build/contractTypes.d.ts.map +1 -0
- package/build/contractTypes.js +28 -0
- package/build/contractTypes.js.map +1 -0
- package/build/countryStats.d.ts +12 -3
- package/build/countryStats.d.ts.map +1 -0
- package/build/countryStats.js +87 -23
- package/build/countryStats.js.map +1 -0
- package/build/deployClient.d.ts +138 -24
- package/build/deployClient.d.ts.map +1 -0
- package/build/deployClient.js +91 -31
- package/build/deployClient.js.map +1 -0
- package/build/deviceIdentity.d.ts +68 -0
- package/build/deviceIdentity.d.ts.map +1 -0
- package/build/deviceIdentity.js +209 -0
- package/build/deviceIdentity.js.map +1 -0
- package/build/freezeClient.d.ts +26 -6
- package/build/freezeClient.d.ts.map +1 -0
- package/build/freezeClient.js +30 -6
- package/build/freezeClient.js.map +1 -0
- package/build/generationClient.d.ts +6 -3
- package/build/generationClient.d.ts.map +1 -0
- package/build/generationClient.js +25 -38
- package/build/generationClient.js.map +1 -0
- package/build/holderSecret.d.ts +70 -0
- package/build/holderSecret.d.ts.map +1 -0
- package/build/holderSecret.js +76 -0
- package/build/holderSecret.js.map +1 -0
- package/build/index.d.ts +38 -38
- package/build/index.d.ts.map +1 -0
- package/build/index.js +97 -121
- package/build/index.js.map +1 -0
- package/build/keysClient.d.ts +142 -0
- package/build/keysClient.d.ts.map +1 -0
- package/build/keysClient.js +109 -0
- package/build/keysClient.js.map +1 -0
- package/build/licenseLeaf.d.ts +76 -0
- package/build/licenseLeaf.d.ts.map +1 -0
- package/build/licenseLeaf.js +189 -0
- package/build/licenseLeaf.js.map +1 -0
- package/build/licenseRecord.d.ts +68 -5
- package/build/licenseRecord.d.ts.map +1 -0
- package/build/licenseRecord.js +26 -1
- package/build/licenseRecord.js.map +1 -0
- package/build/licenseStore.d.ts +81 -4
- package/build/licenseStore.d.ts.map +1 -0
- package/build/licenseStore.js +400 -30
- package/build/licenseStore.js.map +1 -0
- package/build/licenseTrustless.d.ts +43 -0
- package/build/licenseTrustless.d.ts.map +1 -0
- package/build/licenseTrustless.js +180 -0
- package/build/licenseTrustless.js.map +1 -0
- package/build/manifestVerify.d.ts +29 -1
- package/build/manifestVerify.d.ts.map +1 -0
- package/build/manifestVerify.js +46 -4
- package/build/manifestVerify.js.map +1 -0
- package/build/minaPriceHistory.d.ts +9 -0
- package/build/minaPriceHistory.d.ts.map +1 -0
- package/build/minaPriceHistory.js +152 -0
- package/build/minaPriceHistory.js.map +1 -0
- package/build/onChainRoot.d.ts +60 -0
- package/build/onChainRoot.d.ts.map +1 -0
- package/build/onChainRoot.js +74 -0
- package/build/onChainRoot.js.map +1 -0
- package/build/ownershipLicenseHash.d.ts +25 -0
- package/build/ownershipLicenseHash.d.ts.map +1 -0
- package/build/ownershipLicenseHash.js +29 -0
- package/build/ownershipLicenseHash.js.map +1 -0
- package/build/ownershipSignature.d.ts +153 -0
- package/build/ownershipSignature.d.ts.map +1 -0
- package/build/ownershipSignature.js +297 -0
- package/build/ownershipSignature.js.map +1 -0
- package/build/permitCheckFlow.d.ts +155 -0
- package/build/permitCheckFlow.d.ts.map +1 -0
- package/build/permitCheckFlow.js +196 -0
- package/build/permitCheckFlow.js.map +1 -0
- package/build/permitDescribe.d.ts +124 -0
- package/build/permitDescribe.d.ts.map +1 -0
- package/build/permitDescribe.js +324 -0
- package/build/permitDescribe.js.map +1 -0
- package/build/permitInterface.d.ts +85 -0
- package/build/permitInterface.d.ts.map +1 -0
- package/build/permitInterface.js +121 -0
- package/build/permitInterface.js.map +1 -0
- package/build/permitMessages.d.ts +313 -0
- package/build/permitMessages.d.ts.map +1 -0
- package/build/permitMessages.js +462 -0
- package/build/permitMessages.js.map +1 -0
- package/build/permitProof.d.ts +108 -0
- package/build/permitProof.d.ts.map +1 -0
- package/build/permitProof.js +202 -0
- package/build/permitProof.js.map +1 -0
- package/build/permitRegistryRebuild.d.ts +166 -0
- package/build/permitRegistryRebuild.d.ts.map +1 -0
- package/build/permitRegistryRebuild.js +347 -0
- package/build/permitRegistryRebuild.js.map +1 -0
- package/build/permitTree.d.ts +88 -0
- package/build/permitTree.d.ts.map +1 -0
- package/build/permitTree.js +230 -0
- package/build/permitTree.js.map +1 -0
- package/build/permitsClient.d.ts +680 -0
- package/build/permitsClient.d.ts.map +1 -0
- package/build/permitsClient.js +597 -0
- package/build/permitsClient.js.map +1 -0
- package/build/proveErrors.d.ts +50 -0
- package/build/proveErrors.d.ts.map +1 -0
- package/build/proveErrors.js +76 -0
- package/build/proveErrors.js.map +1 -0
- package/build/receipt.d.ts +95 -0
- package/build/receipt.d.ts.map +1 -0
- package/build/receipt.js +84 -0
- package/build/receipt.js.map +1 -0
- package/build/refundClient.d.ts +7 -12
- package/build/refundClient.d.ts.map +1 -0
- package/build/refundClient.js +52 -21
- package/build/refundClient.js.map +1 -0
- package/build/registryTrustVerify.d.ts +78 -0
- package/build/registryTrustVerify.d.ts.map +1 -0
- package/build/registryTrustVerify.js +129 -0
- package/build/registryTrustVerify.js.map +1 -0
- package/build/releaseClient.d.ts +26 -0
- package/build/releaseClient.d.ts.map +1 -0
- package/build/releaseClient.js +65 -0
- package/build/releaseClient.js.map +1 -0
- package/build/renewClient.d.ts +28 -2
- package/build/renewClient.d.ts.map +1 -0
- package/build/renewClient.js +31 -27
- package/build/renewClient.js.map +1 -0
- package/build/seatName.d.ts +8 -0
- package/build/seatName.d.ts.map +1 -0
- package/build/seatName.js +136 -0
- package/build/seatName.js.map +1 -0
- package/build/slotConstants.d.ts +15 -0
- package/build/slotConstants.d.ts.map +1 -0
- package/build/slotConstants.js +17 -0
- package/build/slotConstants.js.map +1 -0
- package/build/statsClient.d.ts +61 -7
- package/build/statsClient.d.ts.map +1 -0
- package/build/statsClient.js +44 -5
- package/build/statsClient.js.map +1 -0
- package/build/successorChain.d.ts +35 -0
- package/build/successorChain.d.ts.map +1 -0
- package/build/successorChain.js +69 -0
- package/build/successorChain.js.map +1 -0
- package/build/taxId.d.ts +44 -0
- package/build/taxId.d.ts.map +1 -0
- package/build/taxId.js +212 -0
- package/build/taxId.js.map +1 -0
- package/build/trustAnchorVerify.d.ts +49 -0
- package/build/trustAnchorVerify.d.ts.map +1 -0
- package/build/trustAnchorVerify.js +432 -0
- package/build/trustAnchorVerify.js.map +1 -0
- package/build/trustAnchorVerifyCli.d.ts +45 -0
- package/build/trustAnchorVerifyCli.d.ts.map +1 -0
- package/build/trustAnchorVerifyCli.js +235 -0
- package/build/trustAnchorVerifyCli.js.map +1 -0
- package/build/txBroadcastClient.d.ts +26 -0
- package/build/txBroadcastClient.d.ts.map +1 -0
- package/build/txBroadcastClient.js +20 -0
- package/build/txBroadcastClient.js.map +1 -0
- package/build/unbindClient.d.ts +77 -0
- package/build/unbindClient.d.ts.map +1 -0
- package/build/unbindClient.js +169 -0
- package/build/unbindClient.js.map +1 -0
- package/build/units.d.ts +28 -0
- package/build/units.d.ts.map +1 -0
- package/build/units.js +65 -0
- package/build/units.js.map +1 -0
- package/build/vatRates.d.ts +54 -0
- package/build/vatRates.d.ts.map +1 -0
- package/build/vatRates.js +82 -0
- package/build/vatRates.js.map +1 -0
- package/build/vatRatesData.d.ts +5 -0
- package/build/vatRatesData.d.ts.map +1 -0
- package/build/vatRatesData.js +42 -0
- package/build/vatRatesData.js.map +1 -0
- package/build/vendorAccountClient.d.ts +66 -0
- package/build/vendorAccountClient.d.ts.map +1 -0
- package/build/vendorAccountClient.js +47 -0
- package/build/vendorAccountClient.js.map +1 -0
- package/build/verifyCore.d.ts +4 -1
- package/build/verifyCore.d.ts.map +1 -0
- package/build/verifyCore.js +21 -10
- package/build/verifyCore.js.map +1 -0
- package/build/verifyOffline.d.ts +85 -0
- package/build/verifyOffline.d.ts.map +1 -0
- package/build/verifyOffline.js +139 -0
- package/build/verifyOffline.js.map +1 -0
- package/build/verifyService.d.ts.map +1 -0
- package/build/verifyService.js +571 -501
- package/build/verifyService.js.map +1 -0
- package/build/verifyWithAncestors.d.ts +19 -0
- package/build/verifyWithAncestors.d.ts.map +1 -0
- package/build/verifyWithAncestors.js +127 -0
- package/build/verifyWithAncestors.js.map +1 -0
- package/build/zipToState.d.ts +2 -0
- package/build/zipToState.d.ts.map +1 -0
- package/build/zipToState.js +94 -0
- package/build/zipToState.js.map +1 -0
- package/package.json +141 -16
- package/src/agent.ts +682 -0
- package/src/agentActions.ts +637 -0
- package/src/agentRecord.ts +121 -0
- package/src/agentVendor.ts +356 -0
- package/src/appsLookup.ts +48 -0
- package/src/archiveBootstrap.ts +386 -0
- package/src/atomicJson.ts +53 -0
- package/src/bindClient.ts +297 -0
- package/src/buyClient.ts +344 -0
- package/src/chainHead.ts +106 -0
- package/src/compactMerkleMap.ts +222 -0
- package/src/contractInterface.ts +465 -0
- package/src/contractTypes.ts +31 -0
- package/src/countryStats.ts +200 -0
- package/src/deployClient.ts +517 -0
- package/src/deviceIdentity.ts +249 -0
- package/src/freezeClient.ts +162 -0
- package/src/generationClient.ts +145 -0
- package/src/holderSecret.ts +91 -0
- package/src/index.ts +362 -0
- package/src/keysClient.ts +135 -0
- package/src/licenseLeaf.ts +221 -0
- package/src/licenseRecord.ts +190 -0
- package/src/licenseStore.ts +767 -0
- package/src/licenseTrustless.ts +207 -0
- package/src/manifestVerify.ts +164 -0
- package/src/minaPriceHistory.ts +166 -0
- package/src/onChainRoot.ts +90 -0
- package/src/ownershipLicenseHash.ts +31 -0
- package/src/ownershipSignature.ts +421 -0
- package/src/permitCheckFlow.ts +227 -0
- package/src/permitDescribe.ts +362 -0
- package/src/permitInterface.ts +146 -0
- package/src/permitMessages.ts +572 -0
- package/src/permitProof.ts +230 -0
- package/src/permitRegistryRebuild.ts +423 -0
- package/src/permitTree.ts +232 -0
- package/src/permitsClient.ts +746 -0
- package/src/proveErrors.ts +98 -0
- package/src/receipt.ts +156 -0
- package/src/refundClient.ts +177 -0
- package/src/registryTrustVerify.ts +192 -0
- package/src/releaseClient.ts +101 -0
- package/src/renewClient.ts +234 -0
- package/src/seatName.ts +165 -0
- package/src/slotConstants.ts +18 -0
- package/src/statsClient.ts +249 -0
- package/src/successorChain.ts +87 -0
- package/src/taxId.ts +227 -0
- package/src/trustAnchorVerify.ts +550 -0
- package/src/trustAnchorVerifyCli.ts +234 -0
- package/src/txBroadcastClient.ts +48 -0
- package/src/unbindClient.ts +233 -0
- package/src/units.ts +74 -0
- package/src/vatRates.ts +100 -0
- package/src/vatRatesData.ts +43 -0
- package/src/vendorAccountClient.ts +120 -0
- package/src/verifyCore.ts +100 -0
- package/src/verifyOffline.ts +212 -0
- package/src/verifyService.ts +982 -0
- package/src/verifyWithAncestors.ts +163 -0
- package/src/zipToState.ts +94 -0
- package/build/licenseProof.d.ts +0 -26
- package/build/licenseProof.js +0 -41
- package/build/migrateClient.d.ts +0 -43
- package/build/migrateClient.js +0 -47
- package/build/ownership.d.ts +0 -34
- package/build/ownership.js +0 -147
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
// Copyright (c) 2025-2026 zkLicensing project developers
|
|
2
|
+
// SPDX-License-Identifier: BUSL-1.1
|
|
3
|
+
/**
|
|
4
|
+
* permitProof.ts — `zklicensing/permits/proof`
|
|
5
|
+
*
|
|
6
|
+
* Zero-knowledge proof that the prover holds an active permit in a registry
|
|
7
|
+
* (PERMITS_PLAN.md §7.2), without revealing which permit or which key:
|
|
8
|
+
*
|
|
9
|
+
* public: registry, root, slot, requiredScope, context
|
|
10
|
+
* output: nullifier = Poseidon(holder secret, context)
|
|
11
|
+
* private: the permit leaf, its Merkle witness, the holder secret, and the
|
|
12
|
+
* holder's signature over (registry, root, context)
|
|
13
|
+
*
|
|
14
|
+
* The verifier checks the proof, that `root` is a recent root of the
|
|
15
|
+
* registry (from a Mina node, or the keeper's /roots), that `slot` is close
|
|
16
|
+
* to now, and — if it wants one use per holder per context — that the
|
|
17
|
+
* nullifier is new. Proving runs on the holder's device: it needs the
|
|
18
|
+
* holder's signature and secret, which never leave it.
|
|
19
|
+
*
|
|
20
|
+
* The holder secret: permit subjects are public (each permit is published
|
|
21
|
+
* with its subject), so a nullifier computed from the subject could be
|
|
22
|
+
* recomputed by anyone for every permit and matched. The nullifier is
|
|
23
|
+
* computed from a secret only the holder's wallet can produce instead: the
|
|
24
|
+
* hash of its text signature over (registry, network, a counter), which is
|
|
25
|
+
* deterministic, so the same wallet re-derives it anywhere from the chain
|
|
26
|
+
* alone (holderSecret.ts). The permit's
|
|
27
|
+
* salt is the hash of that secret, so the keeper and the authority, who see
|
|
28
|
+
* the salt, still cannot compute nullifiers; and one secret per permit keeps
|
|
29
|
+
* one nullifier per permit and context.
|
|
30
|
+
*/
|
|
31
|
+
import { Field, MerkleMapWitness, Poseidon, PublicKey, Signature, Struct, UInt32, ZkProgram } from 'o1js';
|
|
32
|
+
import { PermitLeaf, permitLeafHash, permitSubject, PERMIT_STATUS_ACTIVE, } from './permitMessages.js';
|
|
33
|
+
import { saltFromHolderSecret } from './holderSecret.js';
|
|
34
|
+
/** Tag for the holder's proof signature (distinct from every registry message). */
|
|
35
|
+
export const PERMIT_PROOF_TAG = Field([...'zkPermits/v1/proof'].reduce((v, ch) => (v << 8n) | BigInt(ch.charCodeAt(0)), 0n));
|
|
36
|
+
export const PermitProofInput = Struct({
|
|
37
|
+
registry: PublicKey,
|
|
38
|
+
root: Field,
|
|
39
|
+
slot: UInt32,
|
|
40
|
+
requiredScope: Field,
|
|
41
|
+
context: Field,
|
|
42
|
+
});
|
|
43
|
+
/** The message the holder signs to prove control of the permit's key. */
|
|
44
|
+
export function holderProofMessage(registry, root, context) {
|
|
45
|
+
return [PERMIT_PROOF_TAG, ...registry.toFields(), root, context];
|
|
46
|
+
}
|
|
47
|
+
/** Nullifier: stable per (permit, context), unlinkable across contexts; needs the holder secret. */
|
|
48
|
+
export function permitNullifier(holderSecret, context) {
|
|
49
|
+
return Poseidon.hash([PERMIT_PROOF_TAG, holderSecret, context]);
|
|
50
|
+
}
|
|
51
|
+
// ── Holder secret ─── (holderSecret.ts; re-exported here)
|
|
52
|
+
export { HOLDER_SECRET_TAG, HOLDER_SALT_TAG, holderSecretText, holderSecretFromSignature, saltFromHolderSecret, deriveHolderSecret, findHolderSecret, holderSecretMatches, MAX_HOLDER_SECRETS, } from './holderSecret.js';
|
|
53
|
+
// ── Verifier-bound challenges ───────────────────────────────────────────────
|
|
54
|
+
//
|
|
55
|
+
// The proof's `context` is a public input the verifier chooses, and the
|
|
56
|
+
// nullifier is Poseidon(tag, subject, context). If two verifiers handed out
|
|
57
|
+
// the same raw context, the same holder would give both the same nullifier,
|
|
58
|
+
// and comparing lists would link the two uses. So the context is derived
|
|
59
|
+
// from the verifier's identity and its nonce: verifiers with different
|
|
60
|
+
// identities always get different contexts, whatever nonces they pick. The
|
|
61
|
+
// holder derives it from the identity it actually talks to (a site's
|
|
62
|
+
// origin, a service's address), never from a context the verifier supplies.
|
|
63
|
+
/** Tag for verifier-bound contexts (distinct from PERMIT_PROOF_TAG). */
|
|
64
|
+
export const VERIFIER_CONTEXT_TAG = Field([...'zkPermits/v1/verifier'].reduce((v, ch) => (v << 8n) | BigInt(ch.charCodeAt(0)), 0n));
|
|
65
|
+
/**
|
|
66
|
+
* The canonical form of a verifier identity: a URL becomes its origin
|
|
67
|
+
* (scheme, lower-case host, non-default port; path and query dropped), so
|
|
68
|
+
* `https://Shop.Example/verify?x=1` and `https://shop.example` are the same
|
|
69
|
+
* verifier. Anything else is a service name, trimmed and lower-cased with
|
|
70
|
+
* runs of whitespace collapsed.
|
|
71
|
+
*/
|
|
72
|
+
export function normalizeVerifier(verifier) {
|
|
73
|
+
const raw = String(verifier ?? '').trim();
|
|
74
|
+
let id;
|
|
75
|
+
if (/^[a-z][a-z0-9+.-]*:\/\//i.test(raw)) {
|
|
76
|
+
let origin;
|
|
77
|
+
try {
|
|
78
|
+
origin = new URL(raw).origin;
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
throw new Error(`verifier is not a valid URL: ${raw}`);
|
|
82
|
+
}
|
|
83
|
+
if (!origin || origin === 'null')
|
|
84
|
+
throw new Error(`verifier URL has no origin: ${raw}`);
|
|
85
|
+
id = origin;
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
id = raw.toLowerCase().replace(/\s+/g, ' ');
|
|
89
|
+
}
|
|
90
|
+
if (!id)
|
|
91
|
+
throw new Error('verifier identity is empty');
|
|
92
|
+
if (id.length > 256)
|
|
93
|
+
throw new Error('verifier identity is longer than 256 characters');
|
|
94
|
+
if (/[\u0000-\u001f\u007f]/.test(id))
|
|
95
|
+
throw new Error('verifier identity contains control characters');
|
|
96
|
+
return id;
|
|
97
|
+
}
|
|
98
|
+
/** A fresh 128-bit nonce for a verifier to hand to a holder. */
|
|
99
|
+
export function randomNonce() {
|
|
100
|
+
const b = new Uint8Array(16);
|
|
101
|
+
globalThis.crypto.getRandomValues(b);
|
|
102
|
+
return b.reduce((v, x) => (v << 8n) | BigInt(x), 0n);
|
|
103
|
+
}
|
|
104
|
+
function parseNonce(nonce) {
|
|
105
|
+
const n = typeof nonce === 'bigint' ? nonce : /^\d{1,80}$/.test(String(nonce).trim()) ? BigInt(String(nonce).trim()) : -1n;
|
|
106
|
+
if (n < 0n || n >= 1n << 253n)
|
|
107
|
+
throw new Error('nonce must be a decimal integer below 2^253');
|
|
108
|
+
return n;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* The proof context for `verifier` (see normalizeVerifier) and its `nonce`:
|
|
112
|
+
* Poseidon(VERIFIER_CONTEXT_TAG, byteLength, identity in 31-byte chunks, nonce).
|
|
113
|
+
* Holder and verifier compute it the same way.
|
|
114
|
+
*/
|
|
115
|
+
export function verifierContext(verifier, nonce) {
|
|
116
|
+
const bytes = new TextEncoder().encode(normalizeVerifier(verifier));
|
|
117
|
+
const chunks = [];
|
|
118
|
+
for (let i = 0; i < bytes.length; i += 31) {
|
|
119
|
+
chunks.push(Field(bytes.slice(i, i + 31).reduce((v, x) => (v << 8n) | BigInt(x), 0n)));
|
|
120
|
+
}
|
|
121
|
+
return Poseidon.hash([VERIFIER_CONTEXT_TAG, Field(bytes.length), ...chunks, Field(parseNonce(nonce))]).toBigInt();
|
|
122
|
+
}
|
|
123
|
+
/** In-circuit: every bit set in `required` is set in `scope` (254-bit masks). */
|
|
124
|
+
function assertScopeCovers(scope, required) {
|
|
125
|
+
const s = scope.toBits(254);
|
|
126
|
+
const r = required.toBits(254);
|
|
127
|
+
for (let i = 0; i < 254; i++)
|
|
128
|
+
r[i].not().or(s[i]).assertTrue();
|
|
129
|
+
}
|
|
130
|
+
export const PermitProof = ZkProgram({
|
|
131
|
+
name: 'zkPermits-holder-proof',
|
|
132
|
+
publicInput: PermitProofInput,
|
|
133
|
+
publicOutput: Field,
|
|
134
|
+
methods: {
|
|
135
|
+
prove: {
|
|
136
|
+
privateInputs: [PermitLeaf, MerkleMapWitness, Field, Signature],
|
|
137
|
+
async method(input, leaf, witness, holderSecret, holderSig) {
|
|
138
|
+
const [root, key] = witness.computeRootAndKey(permitLeafHash(leaf));
|
|
139
|
+
root.assertEquals(input.root);
|
|
140
|
+
key.assertEquals(leaf.subject);
|
|
141
|
+
permitSubject(leaf.holderKey, saltFromHolderSecret(holderSecret)).assertEquals(leaf.subject);
|
|
142
|
+
holderSig.verify(leaf.holderKey, holderProofMessage(input.registry, input.root, input.context)).assertTrue();
|
|
143
|
+
leaf.status.assertEquals(PERMIT_STATUS_ACTIVE);
|
|
144
|
+
leaf.validFrom.assertLessThanOrEqual(input.slot);
|
|
145
|
+
input.slot.assertLessThanOrEqual(leaf.expirySlot);
|
|
146
|
+
assertScopeCovers(leaf.scope, input.requiredScope);
|
|
147
|
+
return { publicOutput: permitNullifier(holderSecret, input.context) };
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
});
|
|
152
|
+
/** Holder side: compiles (once) and proves. Returns the proof as JSON. */
|
|
153
|
+
export async function proveHolder(r) {
|
|
154
|
+
const { Bool } = await import('o1js');
|
|
155
|
+
await PermitProof.compile();
|
|
156
|
+
const input = new PermitProofInput({
|
|
157
|
+
registry: PublicKey.fromBase58(r.registry),
|
|
158
|
+
root: Field(r.root),
|
|
159
|
+
slot: UInt32.from(r.slot),
|
|
160
|
+
requiredScope: Field(r.requiredScope),
|
|
161
|
+
context: Field(r.context),
|
|
162
|
+
});
|
|
163
|
+
const witness = new MerkleMapWitness(r.witness.isLefts.map(b => Bool(b)), r.witness.siblings.map(s => Field(s)));
|
|
164
|
+
const { proof } = await PermitProof.prove(input, r.leaf, witness, Field(r.holderSecret), Signature.fromBase58(r.holderSignature));
|
|
165
|
+
return { proof: proof.toJSON(), nullifier: proof.publicOutput.toString() };
|
|
166
|
+
}
|
|
167
|
+
/** Verifier side: checks the proof and its public inputs. Returns the nullifier. */
|
|
168
|
+
export async function verifyHolderProof(proofJson, check) {
|
|
169
|
+
const { verificationKey } = await PermitProof.compile();
|
|
170
|
+
const ProofClass = ZkProgram.Proof(PermitProof);
|
|
171
|
+
let proof;
|
|
172
|
+
try {
|
|
173
|
+
proof = await ProofClass.fromJSON(proofJson);
|
|
174
|
+
}
|
|
175
|
+
catch (e) {
|
|
176
|
+
return { valid: false, nullifier: null, reason: `malformed proof: ${e?.message ?? e}` };
|
|
177
|
+
}
|
|
178
|
+
const pub = proof.publicInput;
|
|
179
|
+
const fail = (reason) => ({ valid: false, nullifier: null, reason });
|
|
180
|
+
if (pub.registry.toBase58() !== check.registry)
|
|
181
|
+
return fail('proof is for another registry');
|
|
182
|
+
if (!check.acceptedRoots.includes(pub.root.toString()))
|
|
183
|
+
return fail('root is not a current root of the registry');
|
|
184
|
+
if (Math.abs(Number(pub.slot.toString()) - check.currentSlot) > (check.maxSlotSkew ?? 10))
|
|
185
|
+
return fail('slot is too far from now');
|
|
186
|
+
if (pub.requiredScope.toBigInt() !== (check.requiredScope ?? 0n))
|
|
187
|
+
return fail('proof is for other scope bits');
|
|
188
|
+
let expected;
|
|
189
|
+
try {
|
|
190
|
+
expected = check.verifier !== undefined ? verifierContext(check.verifier, check.nonce) : check.context;
|
|
191
|
+
}
|
|
192
|
+
catch (e) {
|
|
193
|
+
return fail(e?.message ?? String(e));
|
|
194
|
+
}
|
|
195
|
+
if (pub.context.toBigInt() !== expected)
|
|
196
|
+
return fail('proof is for another context');
|
|
197
|
+
const { verify } = await import('o1js');
|
|
198
|
+
if (!(await verify(proof, verificationKey)))
|
|
199
|
+
return fail('proof does not verify');
|
|
200
|
+
return { valid: true, nullifier: proof.publicOutput.toString(), reason: null };
|
|
201
|
+
}
|
|
202
|
+
//# sourceMappingURL=permitProof.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permitProof.js","sourceRoot":"","sources":["../src/permitProof.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* permitRegistryRebuild.ts — `zklicensing/permits/rebuild`
|
|
3
|
+
*
|
|
4
|
+
* Rebuilds a PermitRegistry's permits tree from its events alone. Every
|
|
5
|
+
* event that changes a permit carries the full new leaf, so the tree is
|
|
6
|
+
* recoverable from the chain without the Keeper (PERMITS_PLAN.md §8.2).
|
|
7
|
+
* The Keeper's indexer uses this same code. Open applications (fees in
|
|
8
|
+
* escrow) are rebuilt the same way: filed minus settled.
|
|
9
|
+
*/
|
|
10
|
+
import { PublicKey, UInt32 } from 'o1js';
|
|
11
|
+
import { CompactMerkleMap } from './compactMerkleMap.js';
|
|
12
|
+
import { Application, PermitLeaf, unpackFees, unpackPolicy } from './permitMessages.js';
|
|
13
|
+
/** A decoded event, as returned by `fetchEvents` (fields we use). */
|
|
14
|
+
export type RegistryEvent = {
|
|
15
|
+
type: string;
|
|
16
|
+
event: {
|
|
17
|
+
data: any;
|
|
18
|
+
};
|
|
19
|
+
blockHeight?: UInt32 | {
|
|
20
|
+
toString(): string;
|
|
21
|
+
};
|
|
22
|
+
globalSlot?: UInt32 | {
|
|
23
|
+
toString(): string;
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
export type PermitRecord = {
|
|
27
|
+
subject: string;
|
|
28
|
+
holderKey: string;
|
|
29
|
+
scope: string;
|
|
30
|
+
validFrom: number;
|
|
31
|
+
expirySlot: number;
|
|
32
|
+
status: number;
|
|
33
|
+
seq: number;
|
|
34
|
+
docHash: string;
|
|
35
|
+
};
|
|
36
|
+
/** An application with its fee in escrow, as JSON (amounts in nanomina, slots as numbers). */
|
|
37
|
+
export type ApplicationRecord = {
|
|
38
|
+
subject: string;
|
|
39
|
+
holderKey: string;
|
|
40
|
+
payer: string;
|
|
41
|
+
baseSeq: number;
|
|
42
|
+
scope: string;
|
|
43
|
+
validFrom: number;
|
|
44
|
+
expirySlot: number;
|
|
45
|
+
docHash: string;
|
|
46
|
+
fee: string;
|
|
47
|
+
processingFee: string;
|
|
48
|
+
deadline: number;
|
|
49
|
+
/** The registry's filing number. */
|
|
50
|
+
filing: number;
|
|
51
|
+
};
|
|
52
|
+
/** How an application ended (APPLICATION_OUTCOME), amounts in nanomina. */
|
|
53
|
+
export type Settlement = {
|
|
54
|
+
subject: string;
|
|
55
|
+
outcome: number;
|
|
56
|
+
kept: string;
|
|
57
|
+
refunded: string;
|
|
58
|
+
};
|
|
59
|
+
export type RegistryView = {
|
|
60
|
+
/** The permits tree (a MerkleMap drop-in that can be saved and loaded without re-hashing). */
|
|
61
|
+
tree: CompactMerkleMap;
|
|
62
|
+
root: string;
|
|
63
|
+
permits: Map<string, PermitRecord>;
|
|
64
|
+
keysHash: string | null;
|
|
65
|
+
epoch: number;
|
|
66
|
+
feesPacked: string | null;
|
|
67
|
+
/** The escrow tree (subject → applicationHash of the open application) and its root. */
|
|
68
|
+
escrow: CompactMerkleMap;
|
|
69
|
+
escrowRoot: string;
|
|
70
|
+
/** Open applications by subject. */
|
|
71
|
+
applications: Map<string, ApplicationRecord>;
|
|
72
|
+
/** Settled applications by application hash: how each ended. */
|
|
73
|
+
settlements: Map<string, Settlement>;
|
|
74
|
+
eventsApplied: number;
|
|
75
|
+
/** Set once the registry was retired (redeployed): its frozen permits root. */
|
|
76
|
+
retiredRoot?: string;
|
|
77
|
+
/** Whether the platform key retired it (retireByPlatform) rather than the authority. */
|
|
78
|
+
retiredByPlatform?: boolean;
|
|
79
|
+
/** Whether it was retired with application fees in escrow (they stay on it). */
|
|
80
|
+
retiredForced?: boolean;
|
|
81
|
+
/**
|
|
82
|
+
* A redeployed registry starts with its predecessor's permits
|
|
83
|
+
* (seededRegistryView): the tree it started with, and each carried-over
|
|
84
|
+
* permit's seq then, so its next change is seq + 1.
|
|
85
|
+
*/
|
|
86
|
+
start?: {
|
|
87
|
+
root: string;
|
|
88
|
+
seqs: Map<string, number>;
|
|
89
|
+
};
|
|
90
|
+
};
|
|
91
|
+
export declare function leafToRecord(leaf: PermitLeaf): PermitRecord;
|
|
92
|
+
export declare function applicationToRecord(app: Application): ApplicationRecord;
|
|
93
|
+
export declare function recordToApplication(r: ApplicationRecord): Application;
|
|
94
|
+
export declare function recordToLeaf(r: PermitRecord): PermitLeaf;
|
|
95
|
+
/**
|
|
96
|
+
* The view a redeployed registry starts with: a copy of its retired
|
|
97
|
+
* predecessor's permits and tree (the initialPermitsRoot its keys signed).
|
|
98
|
+
* Its own events then apply on top; `registryCreated` checks the root.
|
|
99
|
+
*/
|
|
100
|
+
export declare function seededRegistryView(predecessor: RegistryView): RegistryView;
|
|
101
|
+
/**
|
|
102
|
+
* The retired registry a registry continues, from its `registryCreated`
|
|
103
|
+
* event (base58), or null for a first generation. With it a registry's
|
|
104
|
+
* lineage can be walked back on chain events alone; the successor's start
|
|
105
|
+
* was checked against the predecessor's retired root when it was deployed.
|
|
106
|
+
*/
|
|
107
|
+
export declare function registryPredecessor(events: RegistryEvent[]): string | null;
|
|
108
|
+
export declare function emptyRegistryView(): RegistryView;
|
|
109
|
+
/**
|
|
110
|
+
* Applies events in any order. Archive nodes, local chains and paginated
|
|
111
|
+
* fetches don't agree on ordering, so none is assumed: each subject's leaves
|
|
112
|
+
* are ordered by `seq` (the contract advances it by exactly one per change),
|
|
113
|
+
* key rotations by `epoch` and fee changes by `actionNonce`. A gap in a
|
|
114
|
+
* subject's sequence means events are missing, and throws rather than build
|
|
115
|
+
* a wrong tree. Applying to a non-empty view continues from its state.
|
|
116
|
+
*/
|
|
117
|
+
export declare function applyRegistryEvents(view: RegistryView, events: RegistryEvent[]): RegistryView;
|
|
118
|
+
/**
|
|
119
|
+
* Brings `view` up to date with a registry's full event list, re-hashing only
|
|
120
|
+
* the permits whose latest leaf changed: a full rebuild costs a 256-level tree
|
|
121
|
+
* path per permit, a refresh one per changed permit. Returns the subjects
|
|
122
|
+
* that changed (added or updated).
|
|
123
|
+
*/
|
|
124
|
+
export declare function refreshRegistryView(view: RegistryView, events: RegistryEvent[]): string[];
|
|
125
|
+
/** Fetches a registry's events (active Mina instance) and rebuilds its tree. */
|
|
126
|
+
export declare function rebuildRegistry(address: PublicKey | string): Promise<RegistryView>;
|
|
127
|
+
/** 'moved': the holder moved it to a new key (a new permit, under a new subject); this one is closed. */
|
|
128
|
+
export type PermitStatusName = 'active' | 'suspended' | 'revoked' | 'moved' | 'expired' | 'not-yet-valid' | 'in-grace' | 'unknown';
|
|
129
|
+
/**
|
|
130
|
+
* Effective status of a permit at `slot`: revoked and suspended win, then the
|
|
131
|
+
* dates. `gracePeriod` comes from the registry policy.
|
|
132
|
+
*/
|
|
133
|
+
/**
|
|
134
|
+
* A permit's status at `slot`. With the registry's `forkActivationSlot`
|
|
135
|
+
* (a successor deployed after a Mina hard fork): a permit that lapsed
|
|
136
|
+
* shortly before the fork, while its registry was retired and couldn't
|
|
137
|
+
* renew it, counts as expiring at the fork slot, so its grace runs from the
|
|
138
|
+
* fork (as licensing's effectiveExpirySlot). Anonymous holder proofs check
|
|
139
|
+
* the expiry as granted.
|
|
140
|
+
*/
|
|
141
|
+
export declare function permitStatusAt(rec: PermitRecord | undefined, slot: number, gracePeriod?: number, forkActivationSlot?: number): PermitStatusName;
|
|
142
|
+
export { unpackFees, unpackPolicy };
|
|
143
|
+
/** A registry view saved without its tree's hashes recomputed (see CompactMerkleMap). */
|
|
144
|
+
export type StoredRegistryView = {
|
|
145
|
+
root: string;
|
|
146
|
+
permits: PermitRecord[];
|
|
147
|
+
tree: {
|
|
148
|
+
indices: string;
|
|
149
|
+
leaves: string;
|
|
150
|
+
splits: string;
|
|
151
|
+
};
|
|
152
|
+
/** Open applications (absent in views saved before escrow). */
|
|
153
|
+
applications?: ApplicationRecord[];
|
|
154
|
+
/** A redeployed registry's start (RegistryView.start): its root and the carried-over seqs. */
|
|
155
|
+
start?: {
|
|
156
|
+
root: string;
|
|
157
|
+
seqs: Array<[string, number]>;
|
|
158
|
+
};
|
|
159
|
+
};
|
|
160
|
+
export declare function registryViewToStored(view: RegistryView): StoredRegistryView;
|
|
161
|
+
/**
|
|
162
|
+
* Loads a saved view without re-hashing; its keys, epoch and fees come back
|
|
163
|
+
* with the next refreshRegistryView. Throws if the copy is inconsistent.
|
|
164
|
+
*/
|
|
165
|
+
export declare function registryViewFromStored(s: StoredRegistryView): RegistryView;
|
|
166
|
+
//# sourceMappingURL=permitRegistryRebuild.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permitRegistryRebuild.d.ts","sourceRoot":"","sources":["../src/permitRegistryRebuild.ts"],"names":[],"mappings":"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"}
|