@sip-protocol/sdk 0.7.3 → 0.7.4
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/LICENSE +21 -0
- package/README.md +267 -0
- package/dist/{TransportWebUSB-TQ7WZ4LE.mjs → TransportWebUSB-YQMAGJAJ.mjs} +12 -9
- package/dist/browser.d.mts +10 -4
- package/dist/browser.d.ts +10 -4
- package/dist/browser.js +47556 -19603
- package/dist/browser.mjs +628 -48
- package/dist/chunk-4GRJ5MAW.mjs +152 -0
- package/dist/chunk-5D7A3L3W.mjs +717 -0
- package/dist/chunk-64AYA5F5.mjs +7834 -0
- package/dist/chunk-GMDGB22A.mjs +379 -0
- package/dist/chunk-I534WKN7.mjs +328 -0
- package/dist/chunk-IBZVA5Y7.mjs +1003 -0
- package/dist/chunk-PRRZAWJE.mjs +223 -0
- package/dist/{chunk-UJCSKKID.mjs → chunk-XGB3TDIC.mjs} +13 -1
- package/dist/{chunk-3M3HNQCW.mjs → chunk-YWGJ77A2.mjs} +28656 -13103
- package/dist/{chunk-6WGN57S2.mjs → chunk-Z3K7W5S3.mjs} +48 -0
- package/dist/constants-LHAAUC2T.mjs +51 -0
- package/dist/dist-2OGQ7FED.mjs +3957 -0
- package/dist/dist-IFHPYLDX.mjs +254 -0
- package/dist/fulfillment_proof-ANHVPKTB.mjs +21 -0
- package/dist/funding_proof-ICFZ5LHY.mjs +21 -0
- package/dist/{index-DIBZHOOQ.d.ts → index-DXh2IGkz.d.ts} +21239 -10304
- package/dist/{index-8MQz13eJ.d.mts → index-DeE1ZzA4.d.mts} +21239 -10304
- package/dist/index.d.mts +9 -3
- package/dist/index.d.ts +9 -3
- package/dist/index.js +48396 -19623
- package/dist/index.mjs +537 -19
- package/dist/interface-Bf7w1PLW.d.mts +679 -0
- package/dist/interface-Bf7w1PLW.d.ts +679 -0
- package/dist/{noir-DKfEzWy9.d.mts → noir-kzbLVTei.d.mts} +31 -21
- package/dist/{noir-DKfEzWy9.d.ts → noir-kzbLVTei.d.ts} +31 -21
- package/dist/proofs/halo2.d.mts +151 -0
- package/dist/proofs/halo2.d.ts +151 -0
- package/dist/proofs/halo2.js +350 -0
- package/dist/proofs/halo2.mjs +11 -0
- package/dist/proofs/kimchi.d.mts +160 -0
- package/dist/proofs/kimchi.d.ts +160 -0
- package/dist/proofs/kimchi.js +431 -0
- package/dist/proofs/kimchi.mjs +13 -0
- package/dist/proofs/noir.d.mts +1 -1
- package/dist/proofs/noir.d.ts +1 -1
- package/dist/proofs/noir.js +74 -18
- package/dist/proofs/noir.mjs +84 -24
- package/dist/solana-U3MEGU7W.mjs +280 -0
- package/dist/validity_proof-3POXLPNY.mjs +21 -0
- package/package.json +54 -21
- package/src/adapters/index.ts +41 -0
- package/src/adapters/jupiter.ts +571 -0
- package/src/adapters/near-intents.ts +135 -0
- package/src/advisor/advisor.ts +653 -0
- package/src/advisor/index.ts +54 -0
- package/src/advisor/tools.ts +303 -0
- package/src/advisor/types.ts +164 -0
- package/src/chains/ethereum/announcement.ts +536 -0
- package/src/chains/ethereum/bnb-optimizations.ts +474 -0
- package/src/chains/ethereum/commitment.ts +522 -0
- package/src/chains/ethereum/constants.ts +462 -0
- package/src/chains/ethereum/deployment.ts +596 -0
- package/src/chains/ethereum/gas-estimation.ts +538 -0
- package/src/chains/ethereum/index.ts +268 -0
- package/src/chains/ethereum/optimizations.ts +614 -0
- package/src/chains/ethereum/privacy-adapter.ts +855 -0
- package/src/chains/ethereum/registry.ts +584 -0
- package/src/chains/ethereum/rpc.ts +905 -0
- package/src/chains/ethereum/stealth.ts +491 -0
- package/src/chains/ethereum/token.ts +790 -0
- package/src/chains/ethereum/transfer.ts +637 -0
- package/src/chains/ethereum/types.ts +456 -0
- package/src/chains/ethereum/viewing-key.ts +455 -0
- package/src/chains/near/commitment.ts +608 -0
- package/src/chains/near/constants.ts +284 -0
- package/src/chains/near/function-call.ts +871 -0
- package/src/chains/near/history.ts +654 -0
- package/src/chains/near/implicit-account.ts +840 -0
- package/src/chains/near/index.ts +393 -0
- package/src/chains/near/native-transfer.ts +658 -0
- package/src/chains/near/nep141.ts +775 -0
- package/src/chains/near/privacy-adapter.ts +889 -0
- package/src/chains/near/resolver.ts +971 -0
- package/src/chains/near/rpc.ts +1016 -0
- package/src/chains/near/stealth.ts +419 -0
- package/src/chains/near/types.ts +317 -0
- package/src/chains/near/viewing-key.ts +876 -0
- package/src/chains/solana/anchor-transfer.ts +386 -0
- package/src/chains/solana/commitment.ts +577 -0
- package/src/chains/solana/constants.ts +126 -12
- package/src/chains/solana/ephemeral-keys.ts +543 -0
- package/src/chains/solana/index.ts +252 -1
- package/src/chains/solana/key-derivation.ts +418 -0
- package/src/chains/solana/kit-compat.ts +334 -0
- package/src/chains/solana/optimizations.ts +560 -0
- package/src/chains/solana/privacy-adapter.ts +605 -0
- package/src/chains/solana/providers/generic.ts +47 -6
- package/src/chains/solana/providers/helius-enhanced-types.ts +336 -0
- package/src/chains/solana/providers/helius-enhanced.ts +623 -0
- package/src/chains/solana/providers/helius.ts +186 -33
- package/src/chains/solana/providers/index.ts +31 -0
- package/src/chains/solana/providers/interface.ts +61 -18
- package/src/chains/solana/providers/quicknode.ts +409 -0
- package/src/chains/solana/providers/triton.ts +426 -0
- package/src/chains/solana/providers/webhook.ts +338 -67
- package/src/chains/solana/rpc-client.ts +1150 -0
- package/src/chains/solana/scan.ts +83 -66
- package/src/chains/solana/sol-transfer.ts +732 -0
- package/src/chains/solana/spl-transfer.ts +886 -0
- package/src/chains/solana/stealth-scanner.ts +703 -0
- package/src/chains/solana/sunspot-verifier.ts +453 -0
- package/src/chains/solana/transaction-builder.ts +755 -0
- package/src/chains/solana/transfer.ts +74 -5
- package/src/chains/solana/types.ts +57 -6
- package/src/chains/solana/utils.ts +110 -0
- package/src/chains/solana/viewing-key.ts +807 -0
- package/src/compliance/fireblocks.ts +921 -0
- package/src/compliance/index.ts +23 -0
- package/src/compliance/range-sas.ts +398 -33
- package/src/config/endpoints.ts +100 -0
- package/src/crypto.ts +11 -8
- package/src/errors.ts +82 -0
- package/src/evm/erc4337-relayer.ts +830 -0
- package/src/evm/index.ts +47 -0
- package/src/fees/calculator.ts +396 -0
- package/src/fees/index.ts +87 -0
- package/src/fees/near-contract.ts +429 -0
- package/src/fees/types.ts +268 -0
- package/src/index.ts +686 -1
- package/src/intent.ts +6 -3
- package/src/logger.ts +324 -0
- package/src/network/index.ts +80 -0
- package/src/network/proxy.ts +691 -0
- package/src/optimizations/index.ts +541 -0
- package/src/oracle/types.ts +1 -0
- package/src/privacy-backends/arcium-types.ts +727 -0
- package/src/privacy-backends/arcium.ts +719 -0
- package/src/privacy-backends/combined-privacy.ts +866 -0
- package/src/privacy-backends/cspl-token.ts +595 -0
- package/src/privacy-backends/cspl-types.ts +512 -0
- package/src/privacy-backends/cspl.ts +907 -0
- package/src/privacy-backends/health.ts +488 -0
- package/src/privacy-backends/inco-types.ts +323 -0
- package/src/privacy-backends/inco.ts +616 -0
- package/src/privacy-backends/index.ts +254 -4
- package/src/privacy-backends/interface.ts +649 -6
- package/src/privacy-backends/lru-cache.ts +343 -0
- package/src/privacy-backends/magicblock.ts +458 -0
- package/src/privacy-backends/mock.ts +258 -0
- package/src/privacy-backends/privacycash.ts +13 -17
- package/src/privacy-backends/private-swap.ts +570 -0
- package/src/privacy-backends/rate-limiter.ts +683 -0
- package/src/privacy-backends/registry.ts +414 -2
- package/src/privacy-backends/router.ts +283 -3
- package/src/privacy-backends/shadowwire.ts +449 -0
- package/src/privacy-backends/sip-native.ts +3 -0
- package/src/privacy-logger.ts +191 -0
- package/src/production-safety.ts +373 -0
- package/src/proofs/aggregator.ts +1029 -0
- package/src/proofs/browser-composer.ts +1150 -0
- package/src/proofs/browser.ts +113 -25
- package/src/proofs/cache/index.ts +127 -0
- package/src/proofs/cache/interface.ts +545 -0
- package/src/proofs/cache/key-generator.ts +188 -0
- package/src/proofs/cache/lru-cache.ts +481 -0
- package/src/proofs/cache/multi-tier-cache.ts +575 -0
- package/src/proofs/cache/persistent-cache.ts +788 -0
- package/src/proofs/compliance-proof.ts +872 -0
- package/src/proofs/composer/base.ts +923 -0
- package/src/proofs/composer/index.ts +25 -0
- package/src/proofs/composer/interface.ts +518 -0
- package/src/proofs/composer/types.ts +383 -0
- package/src/proofs/converters/halo2.ts +452 -0
- package/src/proofs/converters/index.ts +208 -0
- package/src/proofs/converters/interface.ts +363 -0
- package/src/proofs/converters/kimchi.ts +462 -0
- package/src/proofs/converters/noir.ts +451 -0
- package/src/proofs/fallback.ts +888 -0
- package/src/proofs/halo2.ts +42 -0
- package/src/proofs/index.ts +471 -0
- package/src/proofs/interface.ts +13 -0
- package/src/proofs/kimchi.ts +42 -0
- package/src/proofs/lazy.ts +1004 -0
- package/src/proofs/mock.ts +25 -1
- package/src/proofs/noir.ts +110 -29
- package/src/proofs/orchestrator.ts +960 -0
- package/src/proofs/parallel/concurrency.ts +297 -0
- package/src/proofs/parallel/dependency-graph.ts +602 -0
- package/src/proofs/parallel/executor.ts +420 -0
- package/src/proofs/parallel/index.ts +131 -0
- package/src/proofs/parallel/interface.ts +685 -0
- package/src/proofs/parallel/worker-pool.ts +644 -0
- package/src/proofs/providers/halo2.ts +560 -0
- package/src/proofs/providers/index.ts +34 -0
- package/src/proofs/providers/kimchi.ts +641 -0
- package/src/proofs/validator.ts +881 -0
- package/src/proofs/verifier.ts +867 -0
- package/src/quantum/index.ts +112 -0
- package/src/quantum/winternitz-vault.ts +639 -0
- package/src/quantum/wots.ts +611 -0
- package/src/settlement/backends/direct-chain.ts +1 -0
- package/src/settlement/index.ts +9 -0
- package/src/settlement/router.ts +732 -46
- package/src/solana/index.ts +72 -0
- package/src/solana/jito-relayer.ts +687 -0
- package/src/solana/noir-verifier-types.ts +430 -0
- package/src/solana/noir-verifier.ts +816 -0
- package/src/stealth/address-derivation.ts +193 -0
- package/src/stealth/ed25519.ts +431 -0
- package/src/stealth/index.ts +233 -0
- package/src/stealth/meta-address.ts +221 -0
- package/src/stealth/secp256k1.ts +368 -0
- package/src/stealth/utils.ts +194 -0
- package/src/stealth.ts +50 -1504
- package/src/sync/index.ts +106 -0
- package/src/sync/manager.ts +504 -0
- package/src/sync/mock-provider.ts +318 -0
- package/src/sync/oblivious.ts +625 -0
- package/src/tokens/index.ts +15 -0
- package/src/tokens/registry.ts +301 -0
- package/src/utils/deprecation.ts +94 -0
- package/src/utils/index.ts +9 -0
- package/src/wallet/ethereum/index.ts +68 -0
- package/src/wallet/ethereum/metamask-privacy.ts +420 -0
- package/src/wallet/ethereum/multi-wallet.ts +646 -0
- package/src/wallet/ethereum/privacy-adapter.ts +700 -0
- package/src/wallet/ethereum/types.ts +3 -1
- package/src/wallet/ethereum/walletconnect-adapter.ts +675 -0
- package/src/wallet/hardware/index.ts +10 -0
- package/src/wallet/hardware/ledger-privacy.ts +414 -0
- package/src/wallet/index.ts +71 -0
- package/src/wallet/near/adapter.ts +626 -0
- package/src/wallet/near/index.ts +86 -0
- package/src/wallet/near/meteor-wallet.ts +1153 -0
- package/src/wallet/near/my-near-wallet.ts +790 -0
- package/src/wallet/near/wallet-selector.ts +702 -0
- package/src/wallet/solana/adapter.ts +6 -4
- package/src/wallet/solana/index.ts +13 -0
- package/src/wallet/solana/privacy-adapter.ts +567 -0
- package/src/wallet/sui/types.ts +6 -4
- package/src/zcash/rpc-client.ts +13 -6
- package/dist/chunk-2XIVXWHA.mjs +0 -1930
- package/dist/chunk-3INS3PR5.mjs +0 -884
- package/dist/chunk-3OVABDRH.mjs +0 -17096
- package/dist/chunk-7RFRWDCW.mjs +0 -1504
- package/dist/chunk-DLDWZFYC.mjs +0 -1495
- package/dist/chunk-E6SZWREQ.mjs +0 -57
- package/dist/chunk-F6F73W35.mjs +0 -16166
- package/dist/chunk-G33LB27A.mjs +0 -16166
- package/dist/chunk-HGU6HZRC.mjs +0 -231
- package/dist/chunk-L2K34JCU.mjs +0 -1496
- package/dist/chunk-OFDBEIEK.mjs +0 -16166
- package/dist/chunk-SF7YSLF5.mjs +0 -1515
- package/dist/chunk-SN4ZDTVW.mjs +0 -16166
- package/dist/chunk-WWUSGOXE.mjs +0 -17129
- package/dist/constants-VOI7BSLK.mjs +0 -27
- package/dist/index-B71aXVzk.d.ts +0 -13264
- package/dist/index-BYZbDjal.d.ts +0 -11390
- package/dist/index-CHB3KuOB.d.mts +0 -11859
- package/dist/index-CzWPI6Le.d.ts +0 -11859
- package/dist/index-pOIIuwfV.d.mts +0 -13264
- package/dist/index-xbWjohNq.d.mts +0 -11390
- package/dist/solana-4O4K45VU.mjs +0 -46
- package/dist/solana-5EMCTPTS.mjs +0 -46
- package/dist/solana-NDABAZ6P.mjs +0 -56
- package/dist/solana-Q4NAVBTS.mjs +0 -46
- package/dist/solana-ZYO63LY5.mjs +0 -46
|
@@ -0,0 +1,881 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-System Proof Validation
|
|
3
|
+
*
|
|
4
|
+
* Implements validation logic that ensures proofs from different ZK systems
|
|
5
|
+
* can be correctly composed together. This includes validating input/output
|
|
6
|
+
* compatibility, field consistency, and proof linkage integrity.
|
|
7
|
+
*
|
|
8
|
+
* Key features:
|
|
9
|
+
* - Field element compatibility validation
|
|
10
|
+
* - Public input/output type matching
|
|
11
|
+
* - Proof commitment linkage verification
|
|
12
|
+
* - Curve compatibility validation
|
|
13
|
+
* - Semantic validation (proof meaning consistency)
|
|
14
|
+
* - Detailed validation error reports
|
|
15
|
+
*
|
|
16
|
+
* @packageDocumentation
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import type {
|
|
20
|
+
ProofSystem,
|
|
21
|
+
SingleProof,
|
|
22
|
+
ComposedProof,
|
|
23
|
+
HexString,
|
|
24
|
+
} from '@sip-protocol/types'
|
|
25
|
+
|
|
26
|
+
// ─── Types ───────────────────────────────────────────────────────────────────
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Elliptic curve used by a proof system
|
|
30
|
+
*/
|
|
31
|
+
export type EllipticCurve =
|
|
32
|
+
| 'bn254' // Used by Noir (default), Groth16
|
|
33
|
+
| 'bls12-381' // Used by some Plonk implementations
|
|
34
|
+
| 'pallas' // Part of Pasta curves (Halo2, Kimchi)
|
|
35
|
+
| 'vesta' // Part of Pasta curves (Halo2, Kimchi)
|
|
36
|
+
| 'secp256k1' // Bitcoin curve (rarely used for ZK)
|
|
37
|
+
| 'ed25519' // Edwards curve
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Field characteristics for a proof system
|
|
41
|
+
*/
|
|
42
|
+
export interface FieldCharacteristics {
|
|
43
|
+
/** Field modulus (prime p) */
|
|
44
|
+
modulus: bigint
|
|
45
|
+
/** Scalar field size */
|
|
46
|
+
scalarFieldSize: number
|
|
47
|
+
/** Base field size */
|
|
48
|
+
baseFieldSize: number
|
|
49
|
+
/** Whether the field is a prime field */
|
|
50
|
+
isPrimeField: boolean
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* System compatibility information
|
|
55
|
+
*/
|
|
56
|
+
export interface SystemInfo {
|
|
57
|
+
/** Proof system identifier */
|
|
58
|
+
system: ProofSystem
|
|
59
|
+
/** Primary curve used */
|
|
60
|
+
primaryCurve: EllipticCurve
|
|
61
|
+
/** Secondary curve (for cycle of curves) */
|
|
62
|
+
secondaryCurve?: EllipticCurve
|
|
63
|
+
/** Field characteristics */
|
|
64
|
+
field: FieldCharacteristics
|
|
65
|
+
/** Whether system supports recursion */
|
|
66
|
+
supportsRecursion: boolean
|
|
67
|
+
/** Whether system supports IVC (incremental verifiable computation) */
|
|
68
|
+
supportsIVC: boolean
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Validation result for a single check
|
|
73
|
+
*/
|
|
74
|
+
export interface ValidationCheck {
|
|
75
|
+
/** Check identifier */
|
|
76
|
+
checkId: string
|
|
77
|
+
/** Human-readable check name */
|
|
78
|
+
name: string
|
|
79
|
+
/** Whether check passed */
|
|
80
|
+
passed: boolean
|
|
81
|
+
/** Severity if failed */
|
|
82
|
+
severity: 'error' | 'warning' | 'info'
|
|
83
|
+
/** Detailed message */
|
|
84
|
+
message: string
|
|
85
|
+
/** Additional context */
|
|
86
|
+
context?: Record<string, unknown>
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Comprehensive validation report
|
|
91
|
+
*/
|
|
92
|
+
export interface ValidationReport {
|
|
93
|
+
/** Overall validation result */
|
|
94
|
+
valid: boolean
|
|
95
|
+
/** List of checks performed */
|
|
96
|
+
checks: ValidationCheck[]
|
|
97
|
+
/** Number of errors */
|
|
98
|
+
errorCount: number
|
|
99
|
+
/** Number of warnings */
|
|
100
|
+
warningCount: number
|
|
101
|
+
/** Total validation time (ms) */
|
|
102
|
+
validationTimeMs: number
|
|
103
|
+
/** Proofs validated */
|
|
104
|
+
proofsValidated: number
|
|
105
|
+
/** Systems involved */
|
|
106
|
+
systemsInvolved: ProofSystem[]
|
|
107
|
+
/** Compatibility matrix */
|
|
108
|
+
compatibilityMatrix?: CompatibilityEntry[][]
|
|
109
|
+
/** Recommendations for composition */
|
|
110
|
+
recommendations: string[]
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Entry in compatibility matrix
|
|
115
|
+
*/
|
|
116
|
+
export interface CompatibilityEntry {
|
|
117
|
+
/** Source system */
|
|
118
|
+
sourceSystem: ProofSystem
|
|
119
|
+
/** Target system */
|
|
120
|
+
targetSystem: ProofSystem
|
|
121
|
+
/** Whether systems are compatible */
|
|
122
|
+
compatible: boolean
|
|
123
|
+
/** Compatibility level */
|
|
124
|
+
level: 'full' | 'partial' | 'none'
|
|
125
|
+
/** Required conversions */
|
|
126
|
+
requiredConversions: string[]
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Validation options
|
|
131
|
+
*/
|
|
132
|
+
export interface ValidationOptions {
|
|
133
|
+
/** Skip field compatibility check */
|
|
134
|
+
skipFieldCheck?: boolean
|
|
135
|
+
/** Skip curve compatibility check */
|
|
136
|
+
skipCurveCheck?: boolean
|
|
137
|
+
/** Skip input/output matching */
|
|
138
|
+
skipInputOutputCheck?: boolean
|
|
139
|
+
/** Skip linkage verification */
|
|
140
|
+
skipLinkageCheck?: boolean
|
|
141
|
+
/** Strict mode - fail on warnings */
|
|
142
|
+
strictMode?: boolean
|
|
143
|
+
/** Custom system info overrides */
|
|
144
|
+
systemOverrides?: Partial<Record<ProofSystem, Partial<SystemInfo>>>
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// ─── Constants ───────────────────────────────────────────────────────────────
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* BN254 field modulus (used by Noir)
|
|
151
|
+
*/
|
|
152
|
+
const BN254_MODULUS = BigInt('21888242871839275222246405745257275088548364400416034343698204186575808495617')
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Pallas field modulus (used by Halo2, Kimchi)
|
|
156
|
+
*/
|
|
157
|
+
const PALLAS_MODULUS = BigInt('28948022309329048855892746252171976963363056481941560715954676764349967630337')
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Vesta field modulus (used by Halo2, Kimchi)
|
|
161
|
+
*/
|
|
162
|
+
const VESTA_MODULUS = BigInt('28948022309329048855892746252171976963363056481941647379679742748393362948097')
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* BLS12-381 scalar field modulus
|
|
166
|
+
*/
|
|
167
|
+
const BLS12_381_MODULUS = BigInt('52435875175126190479447740508185965837690552500527637822603658699938581184513')
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Default system information for known proof systems
|
|
171
|
+
*/
|
|
172
|
+
export const SYSTEM_INFO: Record<ProofSystem, SystemInfo> = {
|
|
173
|
+
noir: {
|
|
174
|
+
system: 'noir',
|
|
175
|
+
primaryCurve: 'bn254',
|
|
176
|
+
field: {
|
|
177
|
+
modulus: BN254_MODULUS,
|
|
178
|
+
scalarFieldSize: 254,
|
|
179
|
+
baseFieldSize: 254,
|
|
180
|
+
isPrimeField: true,
|
|
181
|
+
},
|
|
182
|
+
supportsRecursion: true,
|
|
183
|
+
supportsIVC: false,
|
|
184
|
+
},
|
|
185
|
+
halo2: {
|
|
186
|
+
system: 'halo2',
|
|
187
|
+
primaryCurve: 'pallas',
|
|
188
|
+
secondaryCurve: 'vesta',
|
|
189
|
+
field: {
|
|
190
|
+
modulus: PALLAS_MODULUS,
|
|
191
|
+
scalarFieldSize: 255,
|
|
192
|
+
baseFieldSize: 255,
|
|
193
|
+
isPrimeField: true,
|
|
194
|
+
},
|
|
195
|
+
supportsRecursion: true,
|
|
196
|
+
supportsIVC: true,
|
|
197
|
+
},
|
|
198
|
+
kimchi: {
|
|
199
|
+
system: 'kimchi',
|
|
200
|
+
primaryCurve: 'pallas',
|
|
201
|
+
secondaryCurve: 'vesta',
|
|
202
|
+
field: {
|
|
203
|
+
modulus: PALLAS_MODULUS,
|
|
204
|
+
scalarFieldSize: 255,
|
|
205
|
+
baseFieldSize: 255,
|
|
206
|
+
isPrimeField: true,
|
|
207
|
+
},
|
|
208
|
+
supportsRecursion: true,
|
|
209
|
+
supportsIVC: true,
|
|
210
|
+
},
|
|
211
|
+
groth16: {
|
|
212
|
+
system: 'groth16',
|
|
213
|
+
primaryCurve: 'bn254',
|
|
214
|
+
field: {
|
|
215
|
+
modulus: BN254_MODULUS,
|
|
216
|
+
scalarFieldSize: 254,
|
|
217
|
+
baseFieldSize: 254,
|
|
218
|
+
isPrimeField: true,
|
|
219
|
+
},
|
|
220
|
+
supportsRecursion: false,
|
|
221
|
+
supportsIVC: false,
|
|
222
|
+
},
|
|
223
|
+
plonk: {
|
|
224
|
+
system: 'plonk',
|
|
225
|
+
primaryCurve: 'bls12-381',
|
|
226
|
+
field: {
|
|
227
|
+
modulus: BLS12_381_MODULUS,
|
|
228
|
+
scalarFieldSize: 255,
|
|
229
|
+
baseFieldSize: 381,
|
|
230
|
+
isPrimeField: true,
|
|
231
|
+
},
|
|
232
|
+
supportsRecursion: true,
|
|
233
|
+
supportsIVC: false,
|
|
234
|
+
},
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Curve family groupings for compatibility
|
|
239
|
+
*/
|
|
240
|
+
const CURVE_FAMILIES: Record<string, EllipticCurve[]> = {
|
|
241
|
+
pasta: ['pallas', 'vesta'],
|
|
242
|
+
bn: ['bn254'],
|
|
243
|
+
bls: ['bls12-381'],
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// ─── Cross-System Validator ──────────────────────────────────────────────────
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* CrossSystemValidator
|
|
250
|
+
*
|
|
251
|
+
* Validates that proofs from different ZK systems can be correctly
|
|
252
|
+
* composed together.
|
|
253
|
+
*
|
|
254
|
+
* @example
|
|
255
|
+
* ```typescript
|
|
256
|
+
* const validator = new CrossSystemValidator()
|
|
257
|
+
*
|
|
258
|
+
* const report = validator.validate([noirProof, halo2Proof])
|
|
259
|
+
*
|
|
260
|
+
* if (!report.valid) {
|
|
261
|
+
* console.log('Validation errors:', report.checks.filter(c => !c.passed))
|
|
262
|
+
* }
|
|
263
|
+
* ```
|
|
264
|
+
*/
|
|
265
|
+
export class CrossSystemValidator {
|
|
266
|
+
private _options: ValidationOptions
|
|
267
|
+
private _systemInfo: Record<ProofSystem, SystemInfo>
|
|
268
|
+
|
|
269
|
+
constructor(options: ValidationOptions = {}) {
|
|
270
|
+
this._options = options
|
|
271
|
+
this._systemInfo = { ...SYSTEM_INFO }
|
|
272
|
+
|
|
273
|
+
// Apply any overrides
|
|
274
|
+
if (options.systemOverrides) {
|
|
275
|
+
for (const [system, override] of Object.entries(options.systemOverrides)) {
|
|
276
|
+
const systemKey = system as ProofSystem
|
|
277
|
+
if (this._systemInfo[systemKey]) {
|
|
278
|
+
this._systemInfo[systemKey] = {
|
|
279
|
+
...this._systemInfo[systemKey],
|
|
280
|
+
...override,
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// ─── Main Validation ─────────────────────────────────────────────────────
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Validate proofs for cross-system composition
|
|
291
|
+
*/
|
|
292
|
+
validate(proofs: SingleProof[], options?: ValidationOptions): ValidationReport {
|
|
293
|
+
const startTime = Date.now()
|
|
294
|
+
const opts = { ...this._options, ...options }
|
|
295
|
+
const checks: ValidationCheck[] = []
|
|
296
|
+
const systems = new Set<ProofSystem>()
|
|
297
|
+
|
|
298
|
+
// Collect systems involved
|
|
299
|
+
for (const proof of proofs) {
|
|
300
|
+
systems.add(proof.metadata.system)
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
const systemsArray = Array.from(systems)
|
|
304
|
+
|
|
305
|
+
// Perform validation checks
|
|
306
|
+
if (!opts.skipFieldCheck) {
|
|
307
|
+
checks.push(...this.validateFieldCompatibility(proofs))
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
if (!opts.skipCurveCheck) {
|
|
311
|
+
checks.push(...this.validateCurveCompatibility(systemsArray))
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
if (!opts.skipInputOutputCheck) {
|
|
315
|
+
checks.push(...this.validateInputOutputMatching(proofs))
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
if (!opts.skipLinkageCheck) {
|
|
319
|
+
checks.push(...this.validateLinkageIntegrity(proofs))
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// Add semantic validation
|
|
323
|
+
checks.push(...this.validateSemanticConsistency(proofs))
|
|
324
|
+
|
|
325
|
+
// Count errors and warnings
|
|
326
|
+
const errorCount = checks.filter(c => !c.passed && c.severity === 'error').length
|
|
327
|
+
const warningCount = checks.filter(c => !c.passed && c.severity === 'warning').length
|
|
328
|
+
|
|
329
|
+
// Determine overall validity
|
|
330
|
+
const valid = opts.strictMode
|
|
331
|
+
? errorCount === 0 && warningCount === 0
|
|
332
|
+
: errorCount === 0
|
|
333
|
+
|
|
334
|
+
// Build compatibility matrix
|
|
335
|
+
const compatibilityMatrix = this.buildCompatibilityMatrix(systemsArray)
|
|
336
|
+
|
|
337
|
+
// Generate recommendations
|
|
338
|
+
const recommendations = this.generateRecommendations(proofs, checks)
|
|
339
|
+
|
|
340
|
+
return {
|
|
341
|
+
valid,
|
|
342
|
+
checks,
|
|
343
|
+
errorCount,
|
|
344
|
+
warningCount,
|
|
345
|
+
validationTimeMs: Date.now() - startTime,
|
|
346
|
+
proofsValidated: proofs.length,
|
|
347
|
+
systemsInvolved: systemsArray,
|
|
348
|
+
compatibilityMatrix,
|
|
349
|
+
recommendations,
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Validate a composed proof
|
|
355
|
+
*/
|
|
356
|
+
validateComposed(composedProof: ComposedProof, options?: ValidationOptions): ValidationReport {
|
|
357
|
+
return this.validate(composedProof.proofs, options)
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* Quick check if two systems are compatible
|
|
362
|
+
*/
|
|
363
|
+
areSystemsCompatible(system1: ProofSystem, system2: ProofSystem): boolean {
|
|
364
|
+
const info1 = this._systemInfo[system1]
|
|
365
|
+
const info2 = this._systemInfo[system2]
|
|
366
|
+
|
|
367
|
+
if (!info1 || !info2) return false
|
|
368
|
+
|
|
369
|
+
// Same system is always compatible
|
|
370
|
+
if (system1 === system2) return true
|
|
371
|
+
|
|
372
|
+
// Check curve family compatibility
|
|
373
|
+
const family1 = this.getCurveFamily(info1.primaryCurve)
|
|
374
|
+
const family2 = this.getCurveFamily(info2.primaryCurve)
|
|
375
|
+
|
|
376
|
+
return family1 === family2
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* Get system information
|
|
381
|
+
*/
|
|
382
|
+
getSystemInfo(system: ProofSystem): SystemInfo | undefined {
|
|
383
|
+
return this._systemInfo[system]
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// ─── Field Validation ────────────────────────────────────────────────────
|
|
387
|
+
|
|
388
|
+
private validateFieldCompatibility(proofs: SingleProof[]): ValidationCheck[] {
|
|
389
|
+
const checks: ValidationCheck[] = []
|
|
390
|
+
|
|
391
|
+
// Group proofs by system
|
|
392
|
+
const proofsBySystem = new Map<ProofSystem, SingleProof[]>()
|
|
393
|
+
for (const proof of proofs) {
|
|
394
|
+
const system = proof.metadata.system
|
|
395
|
+
const existing = proofsBySystem.get(system) || []
|
|
396
|
+
existing.push(proof)
|
|
397
|
+
proofsBySystem.set(system, existing)
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// Validate field sizes between different systems
|
|
401
|
+
const systems = Array.from(proofsBySystem.keys())
|
|
402
|
+
for (let i = 0; i < systems.length; i++) {
|
|
403
|
+
for (let j = i + 1; j < systems.length; j++) {
|
|
404
|
+
const system1 = systems[i]
|
|
405
|
+
const system2 = systems[j]
|
|
406
|
+
const info1 = this._systemInfo[system1]
|
|
407
|
+
const info2 = this._systemInfo[system2]
|
|
408
|
+
|
|
409
|
+
if (!info1 || !info2) continue
|
|
410
|
+
|
|
411
|
+
// Check if field sizes are compatible
|
|
412
|
+
const sizeDiff = Math.abs(info1.field.scalarFieldSize - info2.field.scalarFieldSize)
|
|
413
|
+
const passed = sizeDiff <= 1 // Allow 1-bit difference
|
|
414
|
+
|
|
415
|
+
checks.push({
|
|
416
|
+
checkId: `field-size-${system1}-${system2}`,
|
|
417
|
+
name: `Field Size Compatibility: ${system1} <-> ${system2}`,
|
|
418
|
+
passed,
|
|
419
|
+
severity: passed ? 'info' : 'warning',
|
|
420
|
+
message: passed
|
|
421
|
+
? `Field sizes are compatible (${info1.field.scalarFieldSize} vs ${info2.field.scalarFieldSize} bits)`
|
|
422
|
+
: `Field size mismatch: ${system1} uses ${info1.field.scalarFieldSize}-bit field, ${system2} uses ${info2.field.scalarFieldSize}-bit field`,
|
|
423
|
+
context: {
|
|
424
|
+
system1FieldSize: info1.field.scalarFieldSize,
|
|
425
|
+
system2FieldSize: info2.field.scalarFieldSize,
|
|
426
|
+
},
|
|
427
|
+
})
|
|
428
|
+
|
|
429
|
+
// Check modulus compatibility
|
|
430
|
+
const modulusCompatible = info1.field.modulus === info2.field.modulus
|
|
431
|
+
|
|
432
|
+
checks.push({
|
|
433
|
+
checkId: `field-modulus-${system1}-${system2}`,
|
|
434
|
+
name: `Field Modulus Compatibility: ${system1} <-> ${system2}`,
|
|
435
|
+
passed: modulusCompatible,
|
|
436
|
+
severity: modulusCompatible ? 'info' : 'warning',
|
|
437
|
+
message: modulusCompatible
|
|
438
|
+
? 'Fields use the same modulus'
|
|
439
|
+
: `Different field moduli - may require value conversion`,
|
|
440
|
+
context: {
|
|
441
|
+
sameModulus: modulusCompatible,
|
|
442
|
+
},
|
|
443
|
+
})
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
return checks
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
// ─── Curve Validation ────────────────────────────────────────────────────
|
|
451
|
+
|
|
452
|
+
private validateCurveCompatibility(systems: ProofSystem[]): ValidationCheck[] {
|
|
453
|
+
const checks: ValidationCheck[] = []
|
|
454
|
+
|
|
455
|
+
// Build curve family map
|
|
456
|
+
const familyCount = new Map<string, ProofSystem[]>()
|
|
457
|
+
for (const system of systems) {
|
|
458
|
+
const info = this._systemInfo[system]
|
|
459
|
+
if (!info) continue
|
|
460
|
+
|
|
461
|
+
const family = this.getCurveFamily(info.primaryCurve)
|
|
462
|
+
const existing = familyCount.get(family) || []
|
|
463
|
+
existing.push(system)
|
|
464
|
+
familyCount.set(family, existing)
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
// Check if all systems use curves from the same family
|
|
468
|
+
const families = Array.from(familyCount.keys())
|
|
469
|
+
const allSameFamily = families.length === 1
|
|
470
|
+
|
|
471
|
+
checks.push({
|
|
472
|
+
checkId: 'curve-family-check',
|
|
473
|
+
name: 'Curve Family Consistency',
|
|
474
|
+
passed: allSameFamily,
|
|
475
|
+
severity: allSameFamily ? 'info' : 'error',
|
|
476
|
+
message: allSameFamily
|
|
477
|
+
? `All systems use ${families[0]} curve family`
|
|
478
|
+
: `Multiple curve families detected: ${families.join(', ')}. Cross-family composition requires special handling.`,
|
|
479
|
+
context: {
|
|
480
|
+
families: Object.fromEntries(familyCount),
|
|
481
|
+
},
|
|
482
|
+
})
|
|
483
|
+
|
|
484
|
+
// For each pair, check direct curve compatibility
|
|
485
|
+
for (let i = 0; i < systems.length; i++) {
|
|
486
|
+
for (let j = i + 1; j < systems.length; j++) {
|
|
487
|
+
const system1 = systems[i]
|
|
488
|
+
const system2 = systems[j]
|
|
489
|
+
const info1 = this._systemInfo[system1]
|
|
490
|
+
const info2 = this._systemInfo[system2]
|
|
491
|
+
|
|
492
|
+
if (!info1 || !info2) continue
|
|
493
|
+
|
|
494
|
+
const sameCurve = info1.primaryCurve === info2.primaryCurve
|
|
495
|
+
const cycleCompatible = this.areCycleCompatible(info1, info2)
|
|
496
|
+
|
|
497
|
+
checks.push({
|
|
498
|
+
checkId: `curve-compat-${system1}-${system2}`,
|
|
499
|
+
name: `Curve Compatibility: ${system1} <-> ${system2}`,
|
|
500
|
+
passed: sameCurve || cycleCompatible,
|
|
501
|
+
severity: sameCurve || cycleCompatible ? 'info' : 'warning',
|
|
502
|
+
message: sameCurve
|
|
503
|
+
? `Both use ${info1.primaryCurve} curve`
|
|
504
|
+
: cycleCompatible
|
|
505
|
+
? `Compatible via Pasta cycle (${info1.primaryCurve}/${info2.primaryCurve})`
|
|
506
|
+
: `Different curves: ${info1.primaryCurve} vs ${info2.primaryCurve}`,
|
|
507
|
+
context: {
|
|
508
|
+
curve1: info1.primaryCurve,
|
|
509
|
+
curve2: info2.primaryCurve,
|
|
510
|
+
sameCurve,
|
|
511
|
+
cycleCompatible,
|
|
512
|
+
},
|
|
513
|
+
})
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
return checks
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
private getCurveFamily(curve: EllipticCurve): string {
|
|
521
|
+
for (const [family, curves] of Object.entries(CURVE_FAMILIES)) {
|
|
522
|
+
if (curves.includes(curve)) {
|
|
523
|
+
return family
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
return 'unknown'
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
private areCycleCompatible(info1: SystemInfo, info2: SystemInfo): boolean {
|
|
530
|
+
// Pasta curves form a cycle (Pallas/Vesta)
|
|
531
|
+
const pastaCurves: EllipticCurve[] = ['pallas', 'vesta']
|
|
532
|
+
const info1IsPasta = pastaCurves.includes(info1.primaryCurve) ||
|
|
533
|
+
Boolean(info1.secondaryCurve && pastaCurves.includes(info1.secondaryCurve))
|
|
534
|
+
const info2IsPasta = pastaCurves.includes(info2.primaryCurve) ||
|
|
535
|
+
Boolean(info2.secondaryCurve && pastaCurves.includes(info2.secondaryCurve))
|
|
536
|
+
|
|
537
|
+
return info1IsPasta && info2IsPasta
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
// ─── Input/Output Validation ─────────────────────────────────────────────
|
|
541
|
+
|
|
542
|
+
private validateInputOutputMatching(proofs: SingleProof[]): ValidationCheck[] {
|
|
543
|
+
const checks: ValidationCheck[] = []
|
|
544
|
+
|
|
545
|
+
// Check if public inputs are properly formatted
|
|
546
|
+
for (const proof of proofs) {
|
|
547
|
+
const hasValidInputs = proof.publicInputs.every(input =>
|
|
548
|
+
typeof input === 'string' && input.startsWith('0x')
|
|
549
|
+
)
|
|
550
|
+
|
|
551
|
+
checks.push({
|
|
552
|
+
checkId: `input-format-${proof.id}`,
|
|
553
|
+
name: `Public Input Format: ${proof.id}`,
|
|
554
|
+
passed: hasValidInputs,
|
|
555
|
+
severity: hasValidInputs ? 'info' : 'error',
|
|
556
|
+
message: hasValidInputs
|
|
557
|
+
? `All ${proof.publicInputs.length} public inputs are properly formatted`
|
|
558
|
+
: 'Some public inputs are not in valid hex format',
|
|
559
|
+
context: {
|
|
560
|
+
proofId: proof.id,
|
|
561
|
+
inputCount: proof.publicInputs.length,
|
|
562
|
+
},
|
|
563
|
+
})
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
// Check for input/output linkage between sequential proofs
|
|
567
|
+
for (let i = 0; i < proofs.length - 1; i++) {
|
|
568
|
+
const current = proofs[i]
|
|
569
|
+
const next = proofs[i + 1]
|
|
570
|
+
|
|
571
|
+
// Check if proofs have overlapping public inputs (suggesting linkage)
|
|
572
|
+
const currentInputsSet = new Set(current.publicInputs)
|
|
573
|
+
const hasOverlap = next.publicInputs.some(input => currentInputsSet.has(input))
|
|
574
|
+
|
|
575
|
+
checks.push({
|
|
576
|
+
checkId: `input-linkage-${current.id}-${next.id}`,
|
|
577
|
+
name: `Input Linkage: ${current.id} -> ${next.id}`,
|
|
578
|
+
passed: true, // This is informational
|
|
579
|
+
severity: 'info',
|
|
580
|
+
message: hasOverlap
|
|
581
|
+
? 'Proofs share common public inputs (linked)'
|
|
582
|
+
: 'Proofs have independent public inputs',
|
|
583
|
+
context: {
|
|
584
|
+
sourceProofId: current.id,
|
|
585
|
+
targetProofId: next.id,
|
|
586
|
+
hasOverlap,
|
|
587
|
+
},
|
|
588
|
+
})
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
return checks
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
// ─── Linkage Validation ──────────────────────────────────────────────────
|
|
595
|
+
|
|
596
|
+
private validateLinkageIntegrity(proofs: SingleProof[]): ValidationCheck[] {
|
|
597
|
+
const checks: ValidationCheck[] = []
|
|
598
|
+
|
|
599
|
+
// Check proof chain integrity
|
|
600
|
+
for (let i = 1; i < proofs.length; i++) {
|
|
601
|
+
const prevProof = proofs[i - 1]
|
|
602
|
+
const currProof = proofs[i]
|
|
603
|
+
const currWithLink = currProof as SingleProof & { linkHash?: HexString }
|
|
604
|
+
|
|
605
|
+
if (currWithLink.linkHash) {
|
|
606
|
+
// Verify the link hash
|
|
607
|
+
const expectedHash = this.computeLinkHash(prevProof, currProof)
|
|
608
|
+
const linkValid = expectedHash === currWithLink.linkHash
|
|
609
|
+
|
|
610
|
+
checks.push({
|
|
611
|
+
checkId: `link-integrity-${currProof.id}`,
|
|
612
|
+
name: `Link Integrity: ${prevProof.id} -> ${currProof.id}`,
|
|
613
|
+
passed: linkValid,
|
|
614
|
+
severity: linkValid ? 'info' : 'error',
|
|
615
|
+
message: linkValid
|
|
616
|
+
? 'Proof linkage hash verified'
|
|
617
|
+
: 'Proof linkage hash mismatch - chain integrity compromised',
|
|
618
|
+
context: {
|
|
619
|
+
expectedHash,
|
|
620
|
+
actualHash: currWithLink.linkHash,
|
|
621
|
+
},
|
|
622
|
+
})
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
// Check timestamp ordering
|
|
627
|
+
let timestampOrdered = true
|
|
628
|
+
for (let i = 1; i < proofs.length; i++) {
|
|
629
|
+
if (proofs[i].metadata.generatedAt < proofs[i - 1].metadata.generatedAt) {
|
|
630
|
+
timestampOrdered = false
|
|
631
|
+
break
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
checks.push({
|
|
636
|
+
checkId: 'timestamp-ordering',
|
|
637
|
+
name: 'Proof Timestamp Ordering',
|
|
638
|
+
passed: timestampOrdered,
|
|
639
|
+
severity: timestampOrdered ? 'info' : 'warning',
|
|
640
|
+
message: timestampOrdered
|
|
641
|
+
? 'Proofs are correctly ordered by generation time'
|
|
642
|
+
: 'Proofs are not in chronological order - may indicate incorrect composition',
|
|
643
|
+
})
|
|
644
|
+
|
|
645
|
+
return checks
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
private computeLinkHash(sourceProof: SingleProof, targetProof: SingleProof): HexString {
|
|
649
|
+
const combinedData = sourceProof.proof + targetProof.proof
|
|
650
|
+
let hash = 0
|
|
651
|
+
for (let i = 0; i < combinedData.length; i++) {
|
|
652
|
+
const char = combinedData.charCodeAt(i)
|
|
653
|
+
hash = ((hash << 5) - hash) + char
|
|
654
|
+
hash = hash & hash
|
|
655
|
+
}
|
|
656
|
+
return `0x${Math.abs(hash).toString(16).padStart(64, '0')}` as HexString
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
// ─── Semantic Validation ─────────────────────────────────────────────────
|
|
660
|
+
|
|
661
|
+
private validateSemanticConsistency(proofs: SingleProof[]): ValidationCheck[] {
|
|
662
|
+
const checks: ValidationCheck[] = []
|
|
663
|
+
|
|
664
|
+
// Check circuit ID consistency within same-system proofs
|
|
665
|
+
const circuitsBySystem = new Map<ProofSystem, Set<string>>()
|
|
666
|
+
for (const proof of proofs) {
|
|
667
|
+
const system = proof.metadata.system
|
|
668
|
+
const existing = circuitsBySystem.get(system) || new Set()
|
|
669
|
+
existing.add(proof.metadata.circuitId)
|
|
670
|
+
circuitsBySystem.set(system, existing)
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
for (const [system, circuits] of circuitsBySystem) {
|
|
674
|
+
checks.push({
|
|
675
|
+
checkId: `circuit-diversity-${system}`,
|
|
676
|
+
name: `Circuit Diversity: ${system}`,
|
|
677
|
+
passed: true, // Informational
|
|
678
|
+
severity: 'info',
|
|
679
|
+
message: `${system} proofs use ${circuits.size} distinct circuit(s): ${Array.from(circuits).join(', ')}`,
|
|
680
|
+
context: {
|
|
681
|
+
system,
|
|
682
|
+
circuitCount: circuits.size,
|
|
683
|
+
circuits: Array.from(circuits),
|
|
684
|
+
},
|
|
685
|
+
})
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
// Check for expired proofs
|
|
689
|
+
const now = Date.now()
|
|
690
|
+
for (const proof of proofs) {
|
|
691
|
+
const expiresAt = proof.metadata.expiresAt
|
|
692
|
+
if (expiresAt) {
|
|
693
|
+
const expired = expiresAt < now
|
|
694
|
+
|
|
695
|
+
checks.push({
|
|
696
|
+
checkId: `proof-expiry-${proof.id}`,
|
|
697
|
+
name: `Proof Expiry: ${proof.id}`,
|
|
698
|
+
passed: !expired,
|
|
699
|
+
severity: expired ? 'error' : 'info',
|
|
700
|
+
message: expired
|
|
701
|
+
? `Proof expired at ${new Date(expiresAt).toISOString()}`
|
|
702
|
+
: expiresAt
|
|
703
|
+
? `Proof valid until ${new Date(expiresAt).toISOString()}`
|
|
704
|
+
: 'Proof has no expiry',
|
|
705
|
+
context: {
|
|
706
|
+
proofId: proof.id,
|
|
707
|
+
expiresAt,
|
|
708
|
+
expired,
|
|
709
|
+
},
|
|
710
|
+
})
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
// Check proof size consistency
|
|
715
|
+
const proofSizes = proofs.map(p => p.metadata.proofSizeBytes)
|
|
716
|
+
const avgSize = proofSizes.reduce((a, b) => a + b, 0) / proofSizes.length
|
|
717
|
+
const maxDeviation = Math.max(...proofSizes.map(s => Math.abs(s - avgSize)))
|
|
718
|
+
const sizeConsistent = maxDeviation < avgSize * 2 // Within 200% of average
|
|
719
|
+
|
|
720
|
+
checks.push({
|
|
721
|
+
checkId: 'proof-size-consistency',
|
|
722
|
+
name: 'Proof Size Consistency',
|
|
723
|
+
passed: sizeConsistent,
|
|
724
|
+
severity: sizeConsistent ? 'info' : 'warning',
|
|
725
|
+
message: sizeConsistent
|
|
726
|
+
? `Proof sizes are consistent (avg: ${Math.round(avgSize)} bytes)`
|
|
727
|
+
: `High proof size variance detected (avg: ${Math.round(avgSize)}, max deviation: ${Math.round(maxDeviation)})`,
|
|
728
|
+
context: {
|
|
729
|
+
averageSize: Math.round(avgSize),
|
|
730
|
+
maxDeviation: Math.round(maxDeviation),
|
|
731
|
+
sizes: proofSizes,
|
|
732
|
+
},
|
|
733
|
+
})
|
|
734
|
+
|
|
735
|
+
return checks
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
// ─── Compatibility Matrix ────────────────────────────────────────────────
|
|
739
|
+
|
|
740
|
+
private buildCompatibilityMatrix(systems: ProofSystem[]): CompatibilityEntry[][] {
|
|
741
|
+
const matrix: CompatibilityEntry[][] = []
|
|
742
|
+
|
|
743
|
+
for (const source of systems) {
|
|
744
|
+
const row: CompatibilityEntry[] = []
|
|
745
|
+
for (const target of systems) {
|
|
746
|
+
row.push(this.getCompatibilityEntry(source, target))
|
|
747
|
+
}
|
|
748
|
+
matrix.push(row)
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
return matrix
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
private getCompatibilityEntry(source: ProofSystem, target: ProofSystem): CompatibilityEntry {
|
|
755
|
+
const sourceInfo = this._systemInfo[source]
|
|
756
|
+
const targetInfo = this._systemInfo[target]
|
|
757
|
+
|
|
758
|
+
if (!sourceInfo || !targetInfo) {
|
|
759
|
+
return {
|
|
760
|
+
sourceSystem: source,
|
|
761
|
+
targetSystem: target,
|
|
762
|
+
compatible: false,
|
|
763
|
+
level: 'none',
|
|
764
|
+
requiredConversions: ['unknown-system'],
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
// Same system - full compatibility
|
|
769
|
+
if (source === target) {
|
|
770
|
+
return {
|
|
771
|
+
sourceSystem: source,
|
|
772
|
+
targetSystem: target,
|
|
773
|
+
compatible: true,
|
|
774
|
+
level: 'full',
|
|
775
|
+
requiredConversions: [],
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
// Check curve family
|
|
780
|
+
const sourceFamily = this.getCurveFamily(sourceInfo.primaryCurve)
|
|
781
|
+
const targetFamily = this.getCurveFamily(targetInfo.primaryCurve)
|
|
782
|
+
|
|
783
|
+
if (sourceFamily === targetFamily) {
|
|
784
|
+
// Same curve family - partial compatibility
|
|
785
|
+
return {
|
|
786
|
+
sourceSystem: source,
|
|
787
|
+
targetSystem: target,
|
|
788
|
+
compatible: true,
|
|
789
|
+
level: 'partial',
|
|
790
|
+
requiredConversions: ['format-conversion'],
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
// Different curve families - requires field conversion
|
|
795
|
+
return {
|
|
796
|
+
sourceSystem: source,
|
|
797
|
+
targetSystem: target,
|
|
798
|
+
compatible: true,
|
|
799
|
+
level: 'partial',
|
|
800
|
+
requiredConversions: ['field-conversion', 'format-conversion'],
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
// ─── Recommendations ─────────────────────────────────────────────────────
|
|
805
|
+
|
|
806
|
+
private generateRecommendations(proofs: SingleProof[], checks: ValidationCheck[]): string[] {
|
|
807
|
+
const recommendations: string[] = []
|
|
808
|
+
|
|
809
|
+
// Check for curve incompatibilities
|
|
810
|
+
const curveErrors = checks.filter(c =>
|
|
811
|
+
c.checkId.startsWith('curve-') && !c.passed
|
|
812
|
+
)
|
|
813
|
+
if (curveErrors.length > 0) {
|
|
814
|
+
recommendations.push(
|
|
815
|
+
'Consider using proof systems from the same curve family (e.g., Halo2 + Kimchi for Pasta curves, or Noir + Groth16 for BN254)'
|
|
816
|
+
)
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
// Check for field mismatches
|
|
820
|
+
const fieldWarnings = checks.filter(c =>
|
|
821
|
+
c.checkId.startsWith('field-') && !c.passed
|
|
822
|
+
)
|
|
823
|
+
if (fieldWarnings.length > 0) {
|
|
824
|
+
recommendations.push(
|
|
825
|
+
'Field element values may need conversion when composing proofs from different systems'
|
|
826
|
+
)
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
// Check for expired proofs
|
|
830
|
+
const expiredProofs = checks.filter(c =>
|
|
831
|
+
c.checkId.startsWith('proof-expiry-') && !c.passed
|
|
832
|
+
)
|
|
833
|
+
if (expiredProofs.length > 0) {
|
|
834
|
+
recommendations.push(
|
|
835
|
+
'Regenerate expired proofs before composition'
|
|
836
|
+
)
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
// Suggest batching for same-system proofs
|
|
840
|
+
const proofsBySystem = new Map<ProofSystem, number>()
|
|
841
|
+
for (const proof of proofs) {
|
|
842
|
+
const count = proofsBySystem.get(proof.metadata.system) || 0
|
|
843
|
+
proofsBySystem.set(proof.metadata.system, count + 1)
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
for (const [system, count] of proofsBySystem) {
|
|
847
|
+
if (count > 2) {
|
|
848
|
+
const info = this._systemInfo[system]
|
|
849
|
+
if (info?.supportsRecursion) {
|
|
850
|
+
recommendations.push(
|
|
851
|
+
`Consider using recursive aggregation for the ${count} ${system} proofs`
|
|
852
|
+
)
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
// General optimization suggestion
|
|
858
|
+
if (proofs.length > 5) {
|
|
859
|
+
recommendations.push(
|
|
860
|
+
'For large compositions, consider using parallel verification to improve performance'
|
|
861
|
+
)
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
return recommendations
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
// ─── Factory Function ────────────────────────────────────────────────────────
|
|
869
|
+
|
|
870
|
+
/**
|
|
871
|
+
* Create a cross-system validator with optional configuration
|
|
872
|
+
*/
|
|
873
|
+
export function createCrossSystemValidator(
|
|
874
|
+
options?: ValidationOptions
|
|
875
|
+
): CrossSystemValidator {
|
|
876
|
+
return new CrossSystemValidator(options)
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
// ─── Export Constants ────────────────────────────────────────────────────────
|
|
880
|
+
|
|
881
|
+
export { BN254_MODULUS, PALLAS_MODULUS, VESTA_MODULUS, BLS12_381_MODULUS }
|