@ottochain/sdk 2.3.0 → 2.4.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/contracts/index.js +15 -8
- package/dist/cjs/apps/contracts/state-machines/contract-agreement.js +35 -40
- package/dist/cjs/apps/contracts/state-machines/contract-escrow.js +80 -37
- package/dist/cjs/apps/contracts/state-machines/contract-universal.js +4 -4
- package/dist/cjs/apps/corporate/index.js +2 -2
- package/dist/cjs/apps/corporate/state-machines/corp-board.js +169 -59
- package/dist/cjs/apps/corporate/state-machines/corp-entity.js +245 -47
- package/dist/cjs/apps/corporate/state-machines/corp-securities.js +407 -99
- package/dist/cjs/apps/corporate/state-machines/corp-shareholders.js +151 -37
- package/dist/cjs/apps/governance/index.js +14 -14
- package/dist/cjs/apps/governance/state-machines/dao-multisig.js +58 -40
- package/dist/cjs/apps/governance/state-machines/dao-reputation.js +46 -40
- package/dist/cjs/apps/governance/state-machines/dao-single.js +28 -11
- package/dist/cjs/apps/governance/state-machines/dao-token.js +67 -41
- package/dist/cjs/apps/governance/state-machines/governance-simple.js +93 -61
- package/dist/cjs/apps/governance/state-machines/governance-universal.js +2 -2
- package/dist/cjs/apps/identity/constants.js +55 -14
- package/dist/cjs/apps/identity/index.js +27 -11
- package/dist/cjs/apps/identity/state-machines/identity-agent.js +3 -3
- package/dist/cjs/apps/identity/state-machines/identity-oracle.js +25 -22
- package/dist/cjs/apps/identity/state-machines/identity-registry.js +288 -0
- package/dist/cjs/apps/identity/state-machines/identity-universal.js +3 -3
- package/dist/cjs/apps/identity/state-machines/index.js +3 -1
- package/dist/cjs/apps/index.js +19 -8
- package/dist/cjs/apps/lending/assets.js +223 -0
- package/dist/cjs/apps/lending/credit-scoring.js +87 -0
- package/dist/cjs/apps/lending/eligibility.js +121 -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 +412 -0
- package/dist/cjs/apps/markets/index.js +21 -11
- package/dist/cjs/apps/markets/state-machines/market-auction.js +14 -13
- package/dist/cjs/apps/markets/state-machines/market-crowdfund.js +29 -24
- package/dist/cjs/apps/markets/state-machines/market-group-buy.js +24 -26
- package/dist/cjs/apps/markets/state-machines/market-prediction.js +80 -53
- package/dist/cjs/apps/markets/state-machines/market-universal.js +5 -5
- package/dist/cjs/apps/oracles/index.js +2 -2
- package/dist/cjs/errors.js +3 -3
- package/dist/cjs/generated/google/protobuf/struct.js +4 -4
- 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 +50 -50
- package/dist/cjs/generated/ottochain/apps/corporate/v1/corporate.js +19 -20
- package/dist/cjs/generated/ottochain/apps/governance/v1/governance.js +13 -13
- package/dist/cjs/generated/ottochain/apps/identity/v1/attestation.js +4 -4
- package/dist/cjs/generated/ottochain/apps/identity/v1/identity.js +124 -130
- package/dist/cjs/generated/ottochain/apps/markets/v1/market.js +107 -107
- package/dist/cjs/generated/ottochain/v1/common.js +4 -4
- package/dist/cjs/generated/ottochain/v1/fiber.js +4 -4
- package/dist/cjs/index.js +41 -7
- package/dist/cjs/openapi.js +2 -0
- package/dist/cjs/ottochain/drop-nulls.js +1 -2
- package/dist/cjs/ottochain/genesis-manifest.js +11 -11
- package/dist/cjs/ottochain/index.js +23 -13
- package/dist/cjs/ottochain/metagraph-client.js +65 -8
- package/dist/cjs/ottochain/snapshot.js +11 -12
- package/dist/cjs/ottochain/transaction.js +57 -14
- package/dist/cjs/ottochain/types.js +16 -2
- package/dist/cjs/privacy/index.js +14 -0
- package/dist/cjs/privacy/sealed-bid.js +210 -0
- package/dist/cjs/privacy/shield-app.js +131 -0
- package/dist/cjs/schema/effects.js +40 -0
- package/dist/cjs/schema/fiber-app.js +19 -13
- package/dist/cjs/schema/guard-lint.js +352 -0
- package/dist/cjs/schema/guards.js +246 -0
- package/dist/cjs/signing.js +80 -0
- package/dist/cjs/types.js +2 -3
- package/dist/cjs/validation.js +8 -8
- 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/contracts/index.js +7 -3
- package/dist/esm/apps/contracts/state-machines/contract-agreement.js +35 -40
- package/dist/esm/apps/contracts/state-machines/contract-escrow.js +80 -37
- package/dist/esm/apps/contracts/state-machines/contract-universal.js +4 -4
- package/dist/esm/apps/corporate/state-machines/corp-board.js +169 -59
- package/dist/esm/apps/corporate/state-machines/corp-entity.js +245 -47
- package/dist/esm/apps/corporate/state-machines/corp-securities.js +407 -99
- package/dist/esm/apps/corporate/state-machines/corp-shareholders.js +151 -37
- package/dist/esm/apps/governance/state-machines/dao-multisig.js +58 -40
- package/dist/esm/apps/governance/state-machines/dao-reputation.js +46 -40
- package/dist/esm/apps/governance/state-machines/dao-single.js +28 -11
- package/dist/esm/apps/governance/state-machines/dao-token.js +67 -41
- package/dist/esm/apps/governance/state-machines/governance-simple.js +93 -61
- package/dist/esm/apps/governance/state-machines/governance-universal.js +2 -2
- package/dist/esm/apps/identity/constants.js +51 -12
- package/dist/esm/apps/identity/index.js +12 -7
- package/dist/esm/apps/identity/state-machines/identity-agent.js +3 -3
- package/dist/esm/apps/identity/state-machines/identity-oracle.js +25 -22
- package/dist/esm/apps/identity/state-machines/identity-registry.js +285 -0
- package/dist/esm/apps/identity/state-machines/identity-universal.js +3 -3
- package/dist/esm/apps/identity/state-machines/index.js +1 -0
- package/dist/esm/apps/index.js +1 -0
- package/dist/esm/apps/lending/assets.js +207 -0
- package/dist/esm/apps/lending/credit-scoring.js +81 -0
- package/dist/esm/apps/lending/eligibility.js +115 -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 +409 -0
- package/dist/esm/apps/markets/index.js +8 -4
- package/dist/esm/apps/markets/state-machines/market-auction.js +14 -13
- package/dist/esm/apps/markets/state-machines/market-crowdfund.js +29 -24
- package/dist/esm/apps/markets/state-machines/market-group-buy.js +24 -26
- package/dist/esm/apps/markets/state-machines/market-prediction.js +80 -53
- package/dist/esm/apps/markets/state-machines/market-universal.js +5 -5
- 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 +46 -46
- package/dist/esm/generated/ottochain/apps/identity/v1/identity.js +114 -120
- package/dist/esm/generated/ottochain/apps/markets/v1/market.js +100 -100
- package/dist/esm/index.js +21 -2
- package/dist/esm/openapi.js +1 -0
- package/dist/esm/ottochain/genesis-manifest.js +9 -9
- package/dist/esm/ottochain/index.js +2 -3
- package/dist/esm/ottochain/metagraph-client.js +65 -8
- package/dist/esm/ottochain/snapshot.js +4 -4
- package/dist/esm/ottochain/transaction.js +43 -3
- package/dist/esm/ottochain/types.js +15 -1
- package/dist/esm/privacy/index.js +6 -0
- package/dist/esm/privacy/sealed-bid.js +206 -0
- package/dist/esm/privacy/shield-app.js +127 -0
- package/dist/esm/schema/effects.js +35 -0
- package/dist/esm/schema/fiber-app.js +13 -6
- package/dist/esm/schema/guard-lint.js +346 -0
- package/dist/esm/schema/guards.js +229 -0
- package/dist/esm/signing.js +74 -0
- 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/contracts/index.d.ts +69 -209
- package/dist/types/apps/contracts/state-machines/contract-agreement.d.ts +20 -95
- package/dist/types/apps/contracts/state-machines/contract-escrow.d.ts +46 -112
- package/dist/types/apps/corporate/index.d.ts +1040 -304
- package/dist/types/apps/corporate/state-machines/corp-board.d.ts +188 -52
- package/dist/types/apps/corporate/state-machines/corp-entity.d.ts +267 -62
- package/dist/types/apps/corporate/state-machines/corp-securities.d.ts +355 -131
- package/dist/types/apps/corporate/state-machines/corp-shareholders.d.ts +225 -53
- package/dist/types/apps/governance/index.d.ts +296 -398
- package/dist/types/apps/governance/state-machines/dao-multisig.d.ts +77 -92
- package/dist/types/apps/governance/state-machines/dao-reputation.d.ts +42 -66
- package/dist/types/apps/governance/state-machines/dao-single.d.ts +25 -47
- package/dist/types/apps/governance/state-machines/dao-token.d.ts +60 -49
- package/dist/types/apps/governance/state-machines/governance-simple.d.ts +87 -117
- package/dist/types/apps/governance/state-machines/governance-universal.d.ts +2 -2
- package/dist/types/apps/identity/constants.d.ts +32 -4
- package/dist/types/apps/identity/index.d.ts +378 -94
- package/dist/types/apps/identity/state-machines/identity-oracle.d.ts +16 -87
- package/dist/types/apps/identity/state-machines/identity-registry.d.ts +379 -0
- package/dist/types/apps/identity/state-machines/index.d.ts +1 -0
- package/dist/types/apps/index.d.ts +1 -0
- 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 +548 -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 +528 -0
- package/dist/types/apps/markets/index.d.ts +108 -203
- package/dist/types/apps/markets/state-machines/market-auction.d.ts +13 -37
- package/dist/types/apps/markets/state-machines/market-crowdfund.d.ts +16 -34
- package/dist/types/apps/markets/state-machines/market-group-buy.d.ts +17 -43
- package/dist/types/apps/markets/state-machines/market-prediction.d.ts +51 -72
- package/dist/types/apps/markets/state-machines/market-universal.d.ts +5 -5
- package/dist/types/generated/index.d.ts +5 -5
- package/dist/types/generated/openapi.d.ts +1257 -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/index.d.ts +6 -2
- package/dist/types/openapi.d.ts +22 -0
- package/dist/types/ottochain/genesis-manifest.d.ts +5 -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 +33 -1
- package/dist/types/ottochain/types.d.ts +335 -30
- 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 +34 -0
- package/dist/types/schema/fiber-app.d.ts +1 -2
- package/dist/types/schema/guard-lint.d.ts +111 -0
- package/dist/types/schema/guards.d.ts +134 -0
- package/dist/types/signing.d.ts +45 -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 +27 -13
- 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,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* DataUpdate Signing Wrappers — dropNulls applied internally
|
|
4
|
+
*
|
|
5
|
+
* Metakit (>= 1.8) computes content hashes by recursively dropping
|
|
6
|
+
* null-valued OBJECT fields (array nulls are preserved) before RFC 8785
|
|
7
|
+
* canonicalization (`JsonBinaryCodec.dropNulls`). This makes
|
|
8
|
+
* `Option = None` indistinguishable from an absent field, so schema
|
|
9
|
+
* evolution never changes prior hashes.
|
|
10
|
+
*
|
|
11
|
+
* The upstream `@constellation-network/metagraph-sdk` signs over the
|
|
12
|
+
* payload as-is, so a payload containing explicit nulls would be signed
|
|
13
|
+
* over different bytes than the metagraph hashes — and the node rejects
|
|
14
|
+
* the signature (HTTP 400).
|
|
15
|
+
*
|
|
16
|
+
* These wrappers shadow the upstream dataUpdate signing surface and apply
|
|
17
|
+
* `dropNulls` internally, unconditionally. Standard-mode signing
|
|
18
|
+
* (currency transactions etc.) is passed through unchanged.
|
|
19
|
+
*/
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
exports.signDataUpdate = signDataUpdate;
|
|
22
|
+
exports.createSignedObject = createSignedObject;
|
|
23
|
+
exports.addSignature = addSignature;
|
|
24
|
+
exports.batchSign = batchSign;
|
|
25
|
+
const metagraph_sdk_1 = require("@constellation-network/metagraph-sdk");
|
|
26
|
+
const drop_nulls_js_1 = require("./ottochain/drop-nulls.js");
|
|
27
|
+
function resolveMode(options = {}) {
|
|
28
|
+
if (options.mode)
|
|
29
|
+
return options.mode;
|
|
30
|
+
if (options.isDataUpdate)
|
|
31
|
+
return 'dataUpdate';
|
|
32
|
+
return 'standard';
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Sign data as a DataUpdate, hashing over null-dropped canonical bytes.
|
|
36
|
+
*
|
|
37
|
+
* Applies `dropNulls` internally so that explicit-null and absent optional
|
|
38
|
+
* fields produce identical signatures, matching metakit's content-hash rule
|
|
39
|
+
* (drop null object fields, preserve array nulls, then RFC 8785).
|
|
40
|
+
*/
|
|
41
|
+
function signDataUpdate(data, privateKey) {
|
|
42
|
+
return (0, metagraph_sdk_1.signDataUpdate)((0, drop_nulls_js_1.dropNulls)(data), privateKey);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Create a signed object. In `dataUpdate` mode the signature is computed
|
|
46
|
+
* over the null-dropped canonical bytes (the returned `value` is the
|
|
47
|
+
* caller's original payload, untouched).
|
|
48
|
+
*/
|
|
49
|
+
function createSignedObject(value, privateKey, options = {}) {
|
|
50
|
+
if (resolveMode(options) === 'dataUpdate') {
|
|
51
|
+
const signed = (0, metagraph_sdk_1.createSignedObject)((0, drop_nulls_js_1.dropNulls)(value), privateKey, options);
|
|
52
|
+
return { ...signed, value };
|
|
53
|
+
}
|
|
54
|
+
return (0, metagraph_sdk_1.createSignedObject)(value, privateKey, options);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Add an additional signature to an existing signed object. In
|
|
58
|
+
* `dataUpdate` mode the new signature is computed over the null-dropped
|
|
59
|
+
* canonical bytes of `signed.value`.
|
|
60
|
+
*/
|
|
61
|
+
function addSignature(signed, privateKey, options) {
|
|
62
|
+
const mode = options ? resolveMode(options) : (signed.mode ?? 'standard');
|
|
63
|
+
if (mode === 'dataUpdate') {
|
|
64
|
+
const result = (0, metagraph_sdk_1.addSignature)({ ...signed, value: (0, drop_nulls_js_1.dropNulls)(signed.value) }, privateKey, options);
|
|
65
|
+
return { ...result, value: signed.value };
|
|
66
|
+
}
|
|
67
|
+
return (0, metagraph_sdk_1.addSignature)(signed, privateKey, options);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Create a signed object with multiple signatures at once. In
|
|
71
|
+
* `dataUpdate` mode all signatures are computed over the null-dropped
|
|
72
|
+
* canonical bytes (the returned `value` is the caller's original payload).
|
|
73
|
+
*/
|
|
74
|
+
function batchSign(value, privateKeys, options = {}) {
|
|
75
|
+
if (resolveMode(options) === 'dataUpdate') {
|
|
76
|
+
const signed = (0, metagraph_sdk_1.batchSign)((0, drop_nulls_js_1.dropNulls)(value), privateKeys, options);
|
|
77
|
+
return { ...signed, value };
|
|
78
|
+
}
|
|
79
|
+
return (0, metagraph_sdk_1.batchSign)(value, privateKeys, options);
|
|
80
|
+
}
|
package/dist/cjs/types.js
CHANGED
|
@@ -8,18 +8,17 @@
|
|
|
8
8
|
* @packageDocumentation
|
|
9
9
|
*/
|
|
10
10
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
-
exports.
|
|
11
|
+
exports.isValidAddress = isValidAddress;
|
|
12
|
+
exports.isValidFiberId = isValidFiberId;
|
|
12
13
|
/**
|
|
13
14
|
* Validate a DAG address format.
|
|
14
15
|
*/
|
|
15
16
|
function isValidAddress(value) {
|
|
16
17
|
return /^DAG[0-9a-zA-Z]+$/.test(value);
|
|
17
18
|
}
|
|
18
|
-
exports.isValidAddress = isValidAddress;
|
|
19
19
|
/**
|
|
20
20
|
* Validate a UUID format.
|
|
21
21
|
*/
|
|
22
22
|
function isValidFiberId(value) {
|
|
23
23
|
return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value);
|
|
24
24
|
}
|
|
25
|
-
exports.isValidFiberId = isValidFiberId;
|
package/dist/cjs/validation.js
CHANGED
|
@@ -7,7 +7,14 @@
|
|
|
7
7
|
* @packageDocumentation
|
|
8
8
|
*/
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
exports.
|
|
10
|
+
exports.CompleteContractRequestSchema = exports.AcceptContractRequestSchema = exports.ProposeContractRequestSchema = exports.ContractTermsSchema = exports.PlatformLinkSchema = exports.AgentIdentityRegistrationSchema = exports.TransferParamsSchema = exports.CurrencyTransactionSchema = exports.CurrencyTransactionValueSchema = exports.TransactionReferenceSchema = exports.SignedSchema = exports.SignatureProofSchema = exports.KeyPairSchema = exports.PublicKeySchema = exports.PrivateKeySchema = exports.DagAddressSchema = void 0;
|
|
11
|
+
exports.validate = validate;
|
|
12
|
+
exports.validatePrivateKey = validatePrivateKey;
|
|
13
|
+
exports.validatePublicKey = validatePublicKey;
|
|
14
|
+
exports.validateAddress = validateAddress;
|
|
15
|
+
exports.validateKeyPair = validateKeyPair;
|
|
16
|
+
exports.safeParse = safeParse;
|
|
17
|
+
exports.assert = assert;
|
|
11
18
|
const zod_1 = require("zod");
|
|
12
19
|
const errors_js_1 = require("./errors.js");
|
|
13
20
|
// ============================================================================
|
|
@@ -209,7 +216,6 @@ function validate(schema, data, fieldName) {
|
|
|
209
216
|
}
|
|
210
217
|
return result.data;
|
|
211
218
|
}
|
|
212
|
-
exports.validate = validate;
|
|
213
219
|
/**
|
|
214
220
|
* Validate a private key
|
|
215
221
|
*
|
|
@@ -220,7 +226,6 @@ exports.validate = validate;
|
|
|
220
226
|
function validatePrivateKey(privateKey) {
|
|
221
227
|
return validate(exports.PrivateKeySchema, privateKey, 'privateKey');
|
|
222
228
|
}
|
|
223
|
-
exports.validatePrivateKey = validatePrivateKey;
|
|
224
229
|
/**
|
|
225
230
|
* Validate a public key
|
|
226
231
|
*
|
|
@@ -231,7 +236,6 @@ exports.validatePrivateKey = validatePrivateKey;
|
|
|
231
236
|
function validatePublicKey(publicKey) {
|
|
232
237
|
return validate(exports.PublicKeySchema, publicKey, 'publicKey');
|
|
233
238
|
}
|
|
234
|
-
exports.validatePublicKey = validatePublicKey;
|
|
235
239
|
/**
|
|
236
240
|
* Validate a DAG address
|
|
237
241
|
*
|
|
@@ -242,7 +246,6 @@ exports.validatePublicKey = validatePublicKey;
|
|
|
242
246
|
function validateAddress(address) {
|
|
243
247
|
return validate(exports.DagAddressSchema, address, 'address');
|
|
244
248
|
}
|
|
245
|
-
exports.validateAddress = validateAddress;
|
|
246
249
|
/**
|
|
247
250
|
* Validate a KeyPair
|
|
248
251
|
*
|
|
@@ -253,7 +256,6 @@ exports.validateAddress = validateAddress;
|
|
|
253
256
|
function validateKeyPair(keyPair) {
|
|
254
257
|
return validate(exports.KeyPairSchema, keyPair, 'keyPair');
|
|
255
258
|
}
|
|
256
|
-
exports.validateKeyPair = validateKeyPair;
|
|
257
259
|
/**
|
|
258
260
|
* Safe validation that returns a result object instead of throwing
|
|
259
261
|
*
|
|
@@ -295,7 +297,6 @@ function safeParse(schema, data) {
|
|
|
295
297
|
}),
|
|
296
298
|
};
|
|
297
299
|
}
|
|
298
|
-
exports.safeParse = safeParse;
|
|
299
300
|
/**
|
|
300
301
|
* Assert that a condition is true, throwing ValidationError if not
|
|
301
302
|
*
|
|
@@ -309,4 +310,3 @@ function assert(condition, message, field) {
|
|
|
309
310
|
throw new errors_js_1.ValidationError(message, { field });
|
|
310
311
|
}
|
|
311
312
|
}
|
|
312
|
-
exports.assert = assert;
|
package/dist/cjs/verify.js
CHANGED
|
@@ -5,13 +5,18 @@
|
|
|
5
5
|
* The package embeds `mode: "standard"|"dataUpdate"` in signed objects and
|
|
6
6
|
* its verify() ignores the `isDataUpdate` parameter when `mode` is present.
|
|
7
7
|
* This wrapper strips `mode` so callers' explicit `isDataUpdate` always wins.
|
|
8
|
+
*
|
|
9
|
+
* In dataUpdate mode, verification happens over the null-dropped canonical
|
|
10
|
+
* bytes (drop null object fields, preserve array nulls, then RFC 8785) —
|
|
11
|
+
* mirroring the SDK's dataUpdate signers and metakit's content-hash rule.
|
|
8
12
|
*/
|
|
9
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
exports.verify =
|
|
14
|
+
exports.verify = verify;
|
|
11
15
|
const metagraph_sdk_1 = require("@constellation-network/metagraph-sdk");
|
|
16
|
+
const drop_nulls_js_1 = require("./ottochain/drop-nulls.js");
|
|
12
17
|
function verify(signed, isDataUpdate) {
|
|
13
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
14
18
|
const { mode, ...rest } = signed;
|
|
15
|
-
|
|
19
|
+
const isDU = isDataUpdate ?? mode === 'dataUpdate';
|
|
20
|
+
const target = isDU ? { ...rest, value: (0, drop_nulls_js_1.dropNulls)(signed.value) } : rest;
|
|
21
|
+
return (0, metagraph_sdk_1.verify)(target, isDU);
|
|
16
22
|
}
|
|
17
|
-
exports.verify = verify;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.frToHex = exports.toFr = exports.R = void 0;
|
|
4
|
+
exports.randomSalt = randomSalt;
|
|
5
|
+
exports.poseidonCommitN = poseidonCommitN;
|
|
6
|
+
exports.poseidonCommit = poseidonCommit;
|
|
7
|
+
exports.openCommitment = openCommitment;
|
|
8
|
+
/**
|
|
9
|
+
* Poseidon commitments over BN254 Fr, computed through the JLVM `poseidon` opcode — the SAME
|
|
10
|
+
* byte-for-byte implementation the chain and the Rust/Scala circuits use. We deliberately route
|
|
11
|
+
* through `jsonLogic.apply` rather than reimplementing Poseidon: the opcode locks the field order,
|
|
12
|
+
* the circomlib round constants, and the `0x` 32-byte big-endian Fr encoding every crypto opcode
|
|
13
|
+
* expects (hard acceptance vector: `poseidon([1,2]) == 0x115cc0f5…189a`).
|
|
14
|
+
*
|
|
15
|
+
* (The standalone `poseidonHash`/`encodeFr` functions exist inside `-jlvm` but are NOT part of its
|
|
16
|
+
* public export surface — only the VM opcodes are — so the opcode path is also the only stable one.)
|
|
17
|
+
*/
|
|
18
|
+
const metagraph_sdk_jlvm_1 = require("@constellation-network/metagraph-sdk-jlvm");
|
|
19
|
+
const node_crypto_1 = require("node:crypto");
|
|
20
|
+
/**
|
|
21
|
+
* BN254 (alt_bn128) scalar field modulus R. A public field constant (not a secret / not Poseidon
|
|
22
|
+
* itself); the `poseidon` opcode re-validates canonicity, so this only drives reduction + sampling.
|
|
23
|
+
*/
|
|
24
|
+
exports.R = 21888242871839275222246405745257275088548364400416034343698204186575808495617n;
|
|
25
|
+
/** Reduce an arbitrary bigint into a canonical BN254 Fr element `[0, R)`. */
|
|
26
|
+
const toFr = (x) => ((x % exports.R) + exports.R) % exports.R;
|
|
27
|
+
exports.toFr = toFr;
|
|
28
|
+
/** Encode a field element as the lowercase `0x` 32-byte big-endian hex the crypto opcodes expect. */
|
|
29
|
+
const frToHex = (x) => `0x${(0, exports.toFr)(x).toString(16).padStart(64, '0')}`;
|
|
30
|
+
exports.frToHex = frToHex;
|
|
31
|
+
const bytesToBig = (b) => b.reduce((a, x) => (a << 8n) | BigInt(x), 0n);
|
|
32
|
+
/** A fresh random salt as a canonical Fr (rejection-sampled to avoid modulo bias near R). */
|
|
33
|
+
function randomSalt() {
|
|
34
|
+
for (;;) {
|
|
35
|
+
const v = bytesToBig((0, node_crypto_1.randomBytes)(32));
|
|
36
|
+
if (v < exports.R)
|
|
37
|
+
return v;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/** `cm = Poseidon([...fields, salt])` via the VM's own opcode. Returns the `0x` 32-byte commitment. */
|
|
41
|
+
function poseidonCommitN(fields, saltFr) {
|
|
42
|
+
const inputs = [...fields.map(exports.frToHex), (0, exports.frToHex)(saltFr)];
|
|
43
|
+
// The bundled poseidon supports width t ≤ 5 (≤ 4 inputs incl. the salt); the opcode throws past it.
|
|
44
|
+
return metagraph_sdk_jlvm_1.jsonLogic.apply({ poseidon: inputs }, {});
|
|
45
|
+
}
|
|
46
|
+
/** `cm = Poseidon([fieldFr, saltFr])` — the commitment for one value field (a bid, a score). */
|
|
47
|
+
function poseidonCommit(fieldFr, saltFr) {
|
|
48
|
+
return poseidonCommitN([fieldFr], saltFr);
|
|
49
|
+
}
|
|
50
|
+
/** Commit `fields` under a fresh (or supplied) salt; returns the commitment + opening. */
|
|
51
|
+
function openCommitment(fields, salt = randomSalt()) {
|
|
52
|
+
return { cm: poseidonCommitN(fields, salt), fields, salt };
|
|
53
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.wordOffset = void 0;
|
|
4
|
+
exports.semiPrivateGuard = semiPrivateGuard;
|
|
5
|
+
exports.verifyGroth16Bundle = verifyGroth16Bundle;
|
|
6
|
+
exports.checkSemiPrivateBinding = checkSemiPrivateBinding;
|
|
7
|
+
exports.verifySemiPrivate = verifySemiPrivate;
|
|
8
|
+
/**
|
|
9
|
+
* The semi-private guard: the JLVM predicate a policy embeds, and its client-side mirror.
|
|
10
|
+
*
|
|
11
|
+
* The guard pins THREE facts about the witness the holder carries, using only opcodes metakit
|
|
12
|
+
* already gas-meters — no new `jlvm_pv_decode`, the public-values blob is parsed with native
|
|
13
|
+
* `substr`/`cat`:
|
|
14
|
+
* 1. `groth16_verify[vkey, witness.publicValues, witness.proof]` — the SP1 proof is valid.
|
|
15
|
+
* 2. the `exprHash` word of the public values == the policy's `logicHash` — the proof ran the
|
|
16
|
+
* INTENDED rule (the pinned, legible predicate).
|
|
17
|
+
* 3. the `outputHash` word == `keccak256("true")` — that rule evaluated to TRUE on the hidden data.
|
|
18
|
+
*
|
|
19
|
+
* `publicValues` rides as a `0x` + 256-hex-char string (`0x` | exprHash | dataHash | outputHash | ok),
|
|
20
|
+
* so word w begins at char `2 + 64*w` and is 64 chars wide. `cat("0x", substr(pv, off, 64))` lifts a
|
|
21
|
+
* word back to a `0x`-hex value comparable with a `bytes32` literal. These offsets are the on-chain
|
|
22
|
+
* guard's contract; the Scala policy mirrors this exact shape.
|
|
23
|
+
*/
|
|
24
|
+
const metagraph_sdk_jlvm_1 = require("@constellation-network/metagraph-sdk-jlvm");
|
|
25
|
+
const preimage_1 = require("./preimage");
|
|
26
|
+
const types_1 = require("./types");
|
|
27
|
+
const HEX_PREFIX = 2; // "0x"
|
|
28
|
+
const WORD_HEX = 64; // 32-byte ABI word as hex chars
|
|
29
|
+
/** Char offset of public-values word `w` (0=exprHash, 1=dataHash, 2=outputHash, 3=ok) in the `0x` string. */
|
|
30
|
+
const wordOffset = (w) => HEX_PREFIX + WORD_HEX * w;
|
|
31
|
+
exports.wordOffset = wordOffset;
|
|
32
|
+
/** Lift public-values word `w` back to a `0x`-hex value (`cat("0x", substr(pv, off, 64))`). */
|
|
33
|
+
const pvWord = (w) => ({
|
|
34
|
+
cat: ['0x', { substr: [{ var: 'witness.publicValues' }, (0, exports.wordOffset)(w), WORD_HEX] }],
|
|
35
|
+
});
|
|
36
|
+
/**
|
|
37
|
+
* Build the JLVM guard a `Governed` morphism / mint policy embeds. `vkey` is the zk-jlvm program
|
|
38
|
+
* verification key (a `bytes32` `0x`-hex literal); `logicHash` is the pinned rule's hash (from
|
|
39
|
+
* {@link ExprRegistry.logicHashOf}). Returns plain JSON — feed it into an ASSET policy's guard/mintPolicy
|
|
40
|
+
* (the asset combiner injects the reserved `witness`). In a fiber TRANSITION there is no `witness` key —
|
|
41
|
+
* the proof rides in the event payload, so read `event.witness.*` instead.
|
|
42
|
+
*
|
|
43
|
+
* REPLAY (audit zk-guards): the proven public values commit only {exprHash, dataHash, outputHash, ok} —
|
|
44
|
+
* nothing situational (no fiber / asset / `$ordinal` / nonce). A valid `{publicValues, proof}` is therefore
|
|
45
|
+
* a reusable bearer token, replayable across any action pinning the same vkey + logicHash. Bind the action
|
|
46
|
+
* INSIDE the proven rule (pin a spender/asset/subject, as `reputationCreditRule` pins `subject`) and/or gate
|
|
47
|
+
* with a one-time nonce ledger until the public values carry action context.
|
|
48
|
+
*/
|
|
49
|
+
function semiPrivateGuard(vkey, logicHash, opts = {}) {
|
|
50
|
+
const { requireTrue = true } = opts;
|
|
51
|
+
const clauses = [
|
|
52
|
+
{ groth16_verify: [vkey, { var: 'witness.publicValues' }, { var: 'witness.proof' }] },
|
|
53
|
+
{ '==': [pvWord(0), logicHash] },
|
|
54
|
+
];
|
|
55
|
+
if (requireTrue) {
|
|
56
|
+
clauses.push({ '==': [pvWord(2), preimage_1.KECCAK_TRUE] });
|
|
57
|
+
// ok bit: the final hex pair of word 3 (offset 256) must be "01" — the JLVM run did not error.
|
|
58
|
+
clauses.push({ '==': [{ substr: [{ var: 'witness.publicValues' }, (0, exports.wordOffset)(3) + 62, 2] }, '01'] });
|
|
59
|
+
}
|
|
60
|
+
return { and: clauses };
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Locally run the SAME `groth16_verify` pairing the chain runs (the verifier opcode, not the prover).
|
|
64
|
+
* Returns `false` — never throws — on an invalid/garbage bundle, mirroring the guard's graceful deny.
|
|
65
|
+
*/
|
|
66
|
+
function verifyGroth16Bundle(bundle) {
|
|
67
|
+
try {
|
|
68
|
+
return metagraph_sdk_jlvm_1.jsonLogic.apply({ groth16_verify: [bundle.vkey, bundle.publicValues, bundle.proof] }, {}) === true;
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Check the binding words WITHOUT the pairing: `exprHash == expectedLogicHash`, `ok` set, and
|
|
76
|
+
* (when `requireTrue`) `outputHash == keccak256("true")`. Pair with {@link verifyGroth16Bundle} for
|
|
77
|
+
* the full client-side mirror of the on-chain guard (see {@link verifySemiPrivate}).
|
|
78
|
+
*/
|
|
79
|
+
function checkSemiPrivateBinding(bundle, expectedLogicHash, opts = {}) {
|
|
80
|
+
const { requireTrue = true } = opts;
|
|
81
|
+
const decoded = (0, types_1.decodeJlvmPublicValues)(bundle.publicValues);
|
|
82
|
+
const eq = (a, b) => a.toLowerCase() === b.toLowerCase();
|
|
83
|
+
const reasons = [];
|
|
84
|
+
if (!eq(decoded.exprHash, expectedLogicHash))
|
|
85
|
+
reasons.push(`exprHash ${decoded.exprHash} != expected logicHash ${expectedLogicHash}`);
|
|
86
|
+
if (!decoded.ok)
|
|
87
|
+
reasons.push('ok bit is false (guest evaluation errored)');
|
|
88
|
+
if (requireTrue && !eq(decoded.outputHash, preimage_1.KECCAK_TRUE))
|
|
89
|
+
reasons.push(`outputHash ${decoded.outputHash} != keccak256("true") ${preimage_1.KECCAK_TRUE}`);
|
|
90
|
+
return { ok: reasons.length === 0, reasons, decoded };
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* The full client-side mirror of the on-chain guard: the proof verifies AND its words bind to the
|
|
94
|
+
* pinned rule (and, by default, to a `true` result). Run this before submitting to fail fast instead
|
|
95
|
+
* of paying for an on-chain rejection.
|
|
96
|
+
*/
|
|
97
|
+
function verifySemiPrivate(bundle, expectedLogicHash, opts = {}) {
|
|
98
|
+
const binding = checkSemiPrivateBinding(bundle, expectedLogicHash, opts);
|
|
99
|
+
if (!verifyGroth16Bundle(bundle)) {
|
|
100
|
+
return {
|
|
101
|
+
ok: false,
|
|
102
|
+
reasons: ['groth16_verify failed (invalid proof for this vkey/publicValues)', ...binding.reasons],
|
|
103
|
+
decoded: binding.decoded,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
return binding;
|
|
107
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseGroth16Stdout = exports.SubprocessProver = exports.verifySemiPrivate = exports.checkSemiPrivateBinding = exports.verifyGroth16Bundle = exports.semiPrivateGuard = exports.wordOffset = exports.atMost = exports.atLeast = exports.boundRule = exports.ExprRegistry = exports.pmtWitness = exports.groth16Witness = exports.decodeJlvmPublicValues = exports.openCommitment = exports.poseidonCommitN = exports.poseidonCommit = exports.randomSalt = exports.frToHex = exports.toFr = exports.R = exports.KECCAK_TRUE = exports.dataHash = exports.exprHash = exports.proverPreimage = exports.canonicalForSigning = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* `@ottochain/sdk/zk` — the client-side semi-private tier.
|
|
6
|
+
*
|
|
7
|
+
* Public-by-default, private-by-opt-in: a holder proves (off-chain, via SP1 zk-jlvm) that some
|
|
8
|
+
* PRIVATE data satisfies a PUBLIC, pinned JLVM rule, and carries only `{publicValues, proof}` on a
|
|
9
|
+
* signed op. A policy's {@link semiPrivateGuard} re-verifies the proof and binds it to the pinned
|
|
10
|
+
* rule on-chain — the value stays hidden, the predicate stays legible.
|
|
11
|
+
*
|
|
12
|
+
* The ONE canonical invariant tying it together: the prover is fed `canonicalForSigning(expr)` /
|
|
13
|
+
* `canonicalForSigning(data)`, so a proof's `exprHash` word equals {@link exprHash}`(rule)` equals a
|
|
14
|
+
* policy's `logicHash` — see {@link proverPreimage} and docs/design/client-side-private-data.md §3.0.
|
|
15
|
+
*/
|
|
16
|
+
var preimage_1 = require("./preimage");
|
|
17
|
+
Object.defineProperty(exports, "canonicalForSigning", { enumerable: true, get: function () { return preimage_1.canonicalForSigning; } });
|
|
18
|
+
Object.defineProperty(exports, "proverPreimage", { enumerable: true, get: function () { return preimage_1.proverPreimage; } });
|
|
19
|
+
Object.defineProperty(exports, "exprHash", { enumerable: true, get: function () { return preimage_1.exprHash; } });
|
|
20
|
+
Object.defineProperty(exports, "dataHash", { enumerable: true, get: function () { return preimage_1.dataHash; } });
|
|
21
|
+
Object.defineProperty(exports, "KECCAK_TRUE", { enumerable: true, get: function () { return preimage_1.KECCAK_TRUE; } });
|
|
22
|
+
var commit_1 = require("./commit");
|
|
23
|
+
Object.defineProperty(exports, "R", { enumerable: true, get: function () { return commit_1.R; } });
|
|
24
|
+
Object.defineProperty(exports, "toFr", { enumerable: true, get: function () { return commit_1.toFr; } });
|
|
25
|
+
Object.defineProperty(exports, "frToHex", { enumerable: true, get: function () { return commit_1.frToHex; } });
|
|
26
|
+
Object.defineProperty(exports, "randomSalt", { enumerable: true, get: function () { return commit_1.randomSalt; } });
|
|
27
|
+
Object.defineProperty(exports, "poseidonCommit", { enumerable: true, get: function () { return commit_1.poseidonCommit; } });
|
|
28
|
+
Object.defineProperty(exports, "poseidonCommitN", { enumerable: true, get: function () { return commit_1.poseidonCommitN; } });
|
|
29
|
+
Object.defineProperty(exports, "openCommitment", { enumerable: true, get: function () { return commit_1.openCommitment; } });
|
|
30
|
+
var types_1 = require("./types");
|
|
31
|
+
Object.defineProperty(exports, "decodeJlvmPublicValues", { enumerable: true, get: function () { return types_1.decodeJlvmPublicValues; } });
|
|
32
|
+
var witness_1 = require("./witness");
|
|
33
|
+
Object.defineProperty(exports, "groth16Witness", { enumerable: true, get: function () { return witness_1.groth16Witness; } });
|
|
34
|
+
Object.defineProperty(exports, "pmtWitness", { enumerable: true, get: function () { return witness_1.pmtWitness; } });
|
|
35
|
+
var registry_1 = require("./registry");
|
|
36
|
+
Object.defineProperty(exports, "ExprRegistry", { enumerable: true, get: function () { return registry_1.ExprRegistry; } });
|
|
37
|
+
Object.defineProperty(exports, "boundRule", { enumerable: true, get: function () { return registry_1.boundRule; } });
|
|
38
|
+
Object.defineProperty(exports, "atLeast", { enumerable: true, get: function () { return registry_1.atLeast; } });
|
|
39
|
+
Object.defineProperty(exports, "atMost", { enumerable: true, get: function () { return registry_1.atMost; } });
|
|
40
|
+
var guard_1 = require("./guard");
|
|
41
|
+
Object.defineProperty(exports, "wordOffset", { enumerable: true, get: function () { return guard_1.wordOffset; } });
|
|
42
|
+
Object.defineProperty(exports, "semiPrivateGuard", { enumerable: true, get: function () { return guard_1.semiPrivateGuard; } });
|
|
43
|
+
Object.defineProperty(exports, "verifyGroth16Bundle", { enumerable: true, get: function () { return guard_1.verifyGroth16Bundle; } });
|
|
44
|
+
Object.defineProperty(exports, "checkSemiPrivateBinding", { enumerable: true, get: function () { return guard_1.checkSemiPrivateBinding; } });
|
|
45
|
+
Object.defineProperty(exports, "verifySemiPrivate", { enumerable: true, get: function () { return guard_1.verifySemiPrivate; } });
|
|
46
|
+
var prover_1 = require("./prover");
|
|
47
|
+
Object.defineProperty(exports, "SubprocessProver", { enumerable: true, get: function () { return prover_1.SubprocessProver; } });
|
|
48
|
+
Object.defineProperty(exports, "parseGroth16Stdout", { enumerable: true, get: function () { return prover_1.parseGroth16Stdout; } });
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.KECCAK_TRUE = exports.dataHash = exports.exprHash = void 0;
|
|
4
|
+
exports.canonicalForSigning = canonicalForSigning;
|
|
5
|
+
exports.proverPreimage = proverPreimage;
|
|
6
|
+
/**
|
|
7
|
+
* The ONE canonical path for the semi-private tier.
|
|
8
|
+
*
|
|
9
|
+
* metakit-sdk 1.8.x `canonicalize` = `serializeJcs(dropNullFields)` — it drops null object-fields
|
|
10
|
+
* before RFC 8785 (server-aligned), so it is the EXACT byte string the chain signs over. Feeding
|
|
11
|
+
* the zk-jlvm prover this same string makes the proof's keccak preimage equal the signature
|
|
12
|
+
* preimage — the determinism binding (see docs/design/client-side-private-data.md §3.0).
|
|
13
|
+
*
|
|
14
|
+
* Note the two hashes differ by design: signing is sha256 over the canonical bytes (+ Constellation
|
|
15
|
+
* prefix), the zk-jlvm guest is keccak256 over the canonical bytes — they bind the SAME canonical
|
|
16
|
+
* string, which is the load-bearing invariant.
|
|
17
|
+
*/
|
|
18
|
+
const metagraph_sdk_1 = require("@constellation-network/metagraph-sdk");
|
|
19
|
+
const sha3_js_1 = require("@noble/hashes/sha3.js");
|
|
20
|
+
const utf8 = (s) => new TextEncoder().encode(s);
|
|
21
|
+
const toHex = (b) => Array.from(b, (x) => x.toString(16).padStart(2, '0')).join('');
|
|
22
|
+
/** The single canonical string both the signer and the prover-feed share (JCS ∘ dropNullFields). */
|
|
23
|
+
function canonicalForSigning(x) {
|
|
24
|
+
return (0, metagraph_sdk_1.canonicalize)(x);
|
|
25
|
+
}
|
|
26
|
+
/** keccak256 of the canonical bytes — the value the zk-jlvm guest commits as exprHash / dataHash. */
|
|
27
|
+
function proverPreimage(x) {
|
|
28
|
+
return `0x${toHex((0, sha3_js_1.keccak_256)(utf8(canonicalForSigning(x))))}`;
|
|
29
|
+
}
|
|
30
|
+
/** exprHash of a published JLVM rule (canonicalized + keccak'd). Equals the chain's `logicHash`. */
|
|
31
|
+
const exprHash = (rule) => proverPreimage(rule);
|
|
32
|
+
exports.exprHash = exprHash;
|
|
33
|
+
/** dataHash of a private data context — kept private; only its hash is public. */
|
|
34
|
+
const dataHash = (data) => proverPreimage(data);
|
|
35
|
+
exports.dataHash = dataHash;
|
|
36
|
+
/** `keccak256(canonicalize(true))` — the `outputHash` a guard binds for a "rule returned true" proof. */
|
|
37
|
+
exports.KECCAK_TRUE = proverPreimage(true);
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SubprocessProver = void 0;
|
|
4
|
+
exports.parseGroth16Stdout = parseGroth16Stdout;
|
|
5
|
+
/**
|
|
6
|
+
* Driving the SP1 zk-jlvm host (`rust/zk-jlvm/script`, `--mode groth16`) to produce a
|
|
7
|
+
* {@link Groth16Bundle} from a JLVM `expr` + `data`.
|
|
8
|
+
*
|
|
9
|
+
* THE load-bearing step: the host's guest hashes the RAW `--expr` / `--data` strings
|
|
10
|
+
* (`exprHash = keccak256(expr_bytes)`), so this driver feeds it `canonicalForSigning(expr)` /
|
|
11
|
+
* `canonicalForSigning(data)`. That makes a proof's `exprHash` word equal {@link exprHash}`(rule)`
|
|
12
|
+
* equal a policy's `logicHash` — without it the binding silently never matches.
|
|
13
|
+
*
|
|
14
|
+
* Proving is heavy (SP1; minutes, optionally `SP1_PROVER=cuda`) and needs the Rust toolchain, so this
|
|
15
|
+
* is an out-of-process driver, not an in-SDK prover. Point it at a prebuilt `binaryPath`, or at the
|
|
16
|
+
* crate via `cargoManifestPath`; configure either explicitly or through `ZK_JLVM_BIN` /
|
|
17
|
+
* `ZK_JLVM_MANIFEST` env vars.
|
|
18
|
+
*/
|
|
19
|
+
const preimage_1 = require("./preimage");
|
|
20
|
+
const reLine = (label) => new RegExp(`^${label}:\\s*(0x[0-9a-fA-F]+)\\s*$`, 'm');
|
|
21
|
+
/** Parse the host's `vkey:` / `public values:` / `proof bytes:` stdout lines into a bundle. */
|
|
22
|
+
function parseGroth16Stdout(stdout) {
|
|
23
|
+
const grab = (label, key) => {
|
|
24
|
+
const m = stdout.match(reLine(label));
|
|
25
|
+
if (!m)
|
|
26
|
+
throw new Error(`zk-jlvm host produced no "${label}:" line (could not read ${key})`);
|
|
27
|
+
return m[1].toLowerCase();
|
|
28
|
+
};
|
|
29
|
+
return {
|
|
30
|
+
vkey: grab('vkey', 'vkey'),
|
|
31
|
+
publicValues: grab('public values', 'publicValues'),
|
|
32
|
+
proof: grab('proof bytes', 'proof'),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/** Drives the zk-jlvm host out-of-process. */
|
|
36
|
+
class SubprocessProver {
|
|
37
|
+
constructor(opts = {}) {
|
|
38
|
+
this.opts = opts;
|
|
39
|
+
}
|
|
40
|
+
async proveGroth16(req) {
|
|
41
|
+
// Canonicalize BEFORE proving so exprHash/dataHash bind the same bytes the chain signs over.
|
|
42
|
+
const expr = (0, preimage_1.canonicalForSigning)(req.expr);
|
|
43
|
+
const data = (0, preimage_1.canonicalForSigning)(req.data);
|
|
44
|
+
const modeArgs = ['--mode', 'groth16', '--expr', expr, '--data', data];
|
|
45
|
+
const binaryPath = this.opts.binaryPath ?? process.env.ZK_JLVM_BIN;
|
|
46
|
+
const manifest = this.opts.cargoManifestPath ?? process.env.ZK_JLVM_MANIFEST;
|
|
47
|
+
let command;
|
|
48
|
+
let args;
|
|
49
|
+
if (binaryPath) {
|
|
50
|
+
command = binaryPath;
|
|
51
|
+
args = modeArgs;
|
|
52
|
+
}
|
|
53
|
+
else if (manifest) {
|
|
54
|
+
command = 'cargo';
|
|
55
|
+
args = ['run', '--release', '--manifest-path', manifest, '--', ...modeArgs];
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
throw new Error('SubprocessProver: set `binaryPath` (or ZK_JLVM_BIN), or `cargoManifestPath` (or ZK_JLVM_MANIFEST)');
|
|
59
|
+
}
|
|
60
|
+
const stdout = await this.run(command, args);
|
|
61
|
+
return parseGroth16Stdout(stdout);
|
|
62
|
+
}
|
|
63
|
+
run(command, args) {
|
|
64
|
+
const { env, cwd, timeoutMs = 1800000 } = this.opts;
|
|
65
|
+
// Lazy-load child_process so importing the zk slice stays light for non-proving consumers.
|
|
66
|
+
return import('node:child_process').then(({ spawn }) => new Promise((resolve, reject) => {
|
|
67
|
+
// argv (no shell) — `expr`/`data` are JSON with quotes/braces; never interpolate into a shell.
|
|
68
|
+
const child = spawn(command, args, {
|
|
69
|
+
cwd,
|
|
70
|
+
env: { ...process.env, ...env },
|
|
71
|
+
timeout: timeoutMs,
|
|
72
|
+
});
|
|
73
|
+
let out = '';
|
|
74
|
+
let err = '';
|
|
75
|
+
child.stdout.on('data', (d) => (out += d.toString()));
|
|
76
|
+
child.stderr.on('data', (d) => (err += d.toString()));
|
|
77
|
+
child.on('error', reject);
|
|
78
|
+
child.on('close', (code) => {
|
|
79
|
+
if (code === 0)
|
|
80
|
+
resolve(out);
|
|
81
|
+
else
|
|
82
|
+
reject(new Error(`zk-jlvm host exited ${code}: ${err.trim() || out.trim()}`));
|
|
83
|
+
});
|
|
84
|
+
}));
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
exports.SubprocessProver = SubprocessProver;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.atMost = exports.atLeast = exports.ExprRegistry = void 0;
|
|
4
|
+
exports.boundRule = boundRule;
|
|
5
|
+
/**
|
|
6
|
+
* The expression registry binds a human name → a published JLVM rule → its `logicHash`
|
|
7
|
+
* (`keccak256(canonicalize(rule))`). The `logicHash` is the load-bearing public value: it equals the
|
|
8
|
+
* `exprHash` word a zk-jlvm proof commits AND the literal a semi-private guard pins. Registering a
|
|
9
|
+
* rule with a LITERAL bound ("pin the bound into the rule", e.g. `{">=":[{"var":"score"},700]}`)
|
|
10
|
+
* makes "the proof's exprHash == this logicHash" mean "the hidden value satisfies THIS public,
|
|
11
|
+
* legible rule" — privacy of the value, transparency of the predicate.
|
|
12
|
+
*/
|
|
13
|
+
const preimage_1 = require("./preimage");
|
|
14
|
+
/** A client-side registry mapping rule names to their canonical `logicHash`. */
|
|
15
|
+
class ExprRegistry {
|
|
16
|
+
constructor() {
|
|
17
|
+
this.byName = new Map();
|
|
18
|
+
}
|
|
19
|
+
/** Register (or replace) a named rule; returns the entry with its computed `logicHash`. */
|
|
20
|
+
register(name, rule) {
|
|
21
|
+
const entry = { rule, logicHash: (0, preimage_1.exprHash)(rule) };
|
|
22
|
+
this.byName.set(name, entry);
|
|
23
|
+
return entry;
|
|
24
|
+
}
|
|
25
|
+
/** Whether a rule is registered under `name`. */
|
|
26
|
+
has(name) {
|
|
27
|
+
return this.byName.has(name);
|
|
28
|
+
}
|
|
29
|
+
/** The registered rule, or throw if unknown. */
|
|
30
|
+
ruleOf(name) {
|
|
31
|
+
return this.require(name).rule;
|
|
32
|
+
}
|
|
33
|
+
/** The registered rule's `logicHash`, or throw if unknown. */
|
|
34
|
+
logicHashOf(name) {
|
|
35
|
+
return this.require(name).logicHash;
|
|
36
|
+
}
|
|
37
|
+
/** All registered names, in insertion order. */
|
|
38
|
+
names() {
|
|
39
|
+
return [...this.byName.keys()];
|
|
40
|
+
}
|
|
41
|
+
require(name) {
|
|
42
|
+
const entry = this.byName.get(name);
|
|
43
|
+
if (!entry)
|
|
44
|
+
throw new Error(`ExprRegistry: no rule registered under "${name}"`);
|
|
45
|
+
return entry;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
exports.ExprRegistry = ExprRegistry;
|
|
49
|
+
/**
|
|
50
|
+
* A single-bound predicate `{[op]:[{var:varName}, bound]}` — the "pinned bound" a proof binds to.
|
|
51
|
+
* `bound` stays a JSON primitive (number/string) so the canonical bytes the prover hashes match the
|
|
52
|
+
* canonical bytes the rule registers under (bigint is not JSON-serializable — pre-encode if needed).
|
|
53
|
+
*/
|
|
54
|
+
function boundRule(varName, op, bound) {
|
|
55
|
+
return { [op]: [{ var: varName }, bound] };
|
|
56
|
+
}
|
|
57
|
+
/** `{">=":[{"var":varName}, bound]}` — "the hidden `varName` is at least `bound`". */
|
|
58
|
+
const atLeast = (varName, bound) => boundRule(varName, '>=', bound);
|
|
59
|
+
exports.atLeast = atLeast;
|
|
60
|
+
/** `{"<=":[{"var":varName}, bound]}` — "the hidden `varName` is at most `bound`". */
|
|
61
|
+
const atMost = (varName, bound) => boundRule(varName, '<=', bound);
|
|
62
|
+
exports.atMost = atMost;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* SP1 zk-jlvm public-values types + decode.
|
|
4
|
+
*
|
|
5
|
+
* The guest commits `abi_encode(JlvmPublicValues{ bytes32 exprHash, bytes32 dataHash,
|
|
6
|
+
* bytes32 outputHash, bool ok })` — four 32-byte words, the bool right-aligned in its word.
|
|
7
|
+
* There is no on-chain `jlvm_pv_decode` opcode: the chain guard parses the same blob with the
|
|
8
|
+
* native JLVM `cat`/`substr` ops. This decode mirrors that for client-side binding/inspection.
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.decodeJlvmPublicValues = decodeJlvmPublicValues;
|
|
12
|
+
/**
|
|
13
|
+
* Decode `abi_encode(JlvmPublicValues)`: four 32-byte words `[exprHash | dataHash | outputHash | ok]`.
|
|
14
|
+
* The bool is right-aligned in its word (final byte `0x00`/`0x01`).
|
|
15
|
+
*/
|
|
16
|
+
function decodeJlvmPublicValues(pv) {
|
|
17
|
+
const b = pv.startsWith('0x') ? pv.slice(2) : pv;
|
|
18
|
+
if (b.length < 4 * 64) {
|
|
19
|
+
throw new Error(`publicValues too short: ${b.length} hex chars (need >= 256)`);
|
|
20
|
+
}
|
|
21
|
+
const word = (i) => `0x${b.slice(i * 64, i * 64 + 64)}`;
|
|
22
|
+
return {
|
|
23
|
+
exprHash: word(0),
|
|
24
|
+
dataHash: word(1),
|
|
25
|
+
outputHash: word(2),
|
|
26
|
+
ok: b.slice(3 * 64 + 62, 3 * 64 + 64) !== '00',
|
|
27
|
+
};
|
|
28
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.groth16Witness = groth16Witness;
|
|
4
|
+
exports.pmtWitness = pmtWitness;
|
|
5
|
+
const types_1 = require("./types");
|
|
6
|
+
/**
|
|
7
|
+
* Shape a produced {@link Groth16Bundle} into the on-op witness map (`{publicValues, proof}`) and
|
|
8
|
+
* surface its decoded public values. The vkey rides in the guard, not the witness, so it is dropped.
|
|
9
|
+
*/
|
|
10
|
+
function groth16Witness(bundle) {
|
|
11
|
+
return {
|
|
12
|
+
witness: { publicValues: bundle.publicValues, proof: bundle.proof },
|
|
13
|
+
decoded: (0, types_1.decodeJlvmPublicValues)(bundle.publicValues),
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
/** Shape a Poseidon-Merkle inclusion path into the on-op `pmt_verify` witness map. */
|
|
17
|
+
function pmtWitness(leaf, index, siblings) {
|
|
18
|
+
return { leaf, index, siblings };
|
|
19
|
+
}
|