@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,960 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Proof Composition Orchestrator
|
|
3
|
+
*
|
|
4
|
+
* High-level orchestrator that manages the entire proof composition workflow.
|
|
5
|
+
* Coordinates providers, manages state, handles the composition lifecycle,
|
|
6
|
+
* and provides retry logic with exponential backoff.
|
|
7
|
+
*
|
|
8
|
+
* Key features:
|
|
9
|
+
* - Composition planning (determine which proofs needed)
|
|
10
|
+
* - Provider selection and initialization
|
|
11
|
+
* - Composition state machine
|
|
12
|
+
* - Timeout and cancellation handling
|
|
13
|
+
* - Retry logic with exponential backoff
|
|
14
|
+
* - Composition audit logging
|
|
15
|
+
* - Composition templates for common patterns
|
|
16
|
+
* - Dry-run/preview support
|
|
17
|
+
*
|
|
18
|
+
* @packageDocumentation
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import { randomBytes, bytesToHex } from '@noble/hashes/utils'
|
|
22
|
+
|
|
23
|
+
import type {
|
|
24
|
+
ProofSystem,
|
|
25
|
+
SingleProof,
|
|
26
|
+
ComposedProof,
|
|
27
|
+
ProofAggregationStrategy,
|
|
28
|
+
HexString,
|
|
29
|
+
} from '@sip-protocol/types'
|
|
30
|
+
|
|
31
|
+
import {
|
|
32
|
+
ProofAggregationStrategy as Strategy,
|
|
33
|
+
ComposedProofStatus,
|
|
34
|
+
} from '@sip-protocol/types'
|
|
35
|
+
|
|
36
|
+
import type { ComposableProofProvider } from './composer/interface'
|
|
37
|
+
import type { ProofGenerationRequest } from './composer/types'
|
|
38
|
+
import { CrossSystemValidator } from './validator'
|
|
39
|
+
import type { ValidationReport } from './validator'
|
|
40
|
+
|
|
41
|
+
// ─── Types ───────────────────────────────────────────────────────────────────
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Orchestrator configuration
|
|
45
|
+
*/
|
|
46
|
+
export interface OrchestratorConfig {
|
|
47
|
+
/** Maximum retries for failed operations */
|
|
48
|
+
maxRetries: number
|
|
49
|
+
/** Base delay for exponential backoff (ms) */
|
|
50
|
+
baseDelayMs: number
|
|
51
|
+
/** Maximum delay between retries (ms) */
|
|
52
|
+
maxDelayMs: number
|
|
53
|
+
/** Overall composition timeout (ms) */
|
|
54
|
+
timeoutMs: number
|
|
55
|
+
/** Enable audit logging */
|
|
56
|
+
enableAuditLog: boolean
|
|
57
|
+
/** Enable dry-run mode by default */
|
|
58
|
+
dryRunDefault: boolean
|
|
59
|
+
/** Validate proofs before composition */
|
|
60
|
+
validateBeforeCompose: boolean
|
|
61
|
+
/** Strict validation mode */
|
|
62
|
+
strictValidation: boolean
|
|
63
|
+
/** Enable parallel provider initialization */
|
|
64
|
+
parallelInit: boolean
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Composition state
|
|
69
|
+
*/
|
|
70
|
+
export type CompositionState =
|
|
71
|
+
| 'idle'
|
|
72
|
+
| 'planning'
|
|
73
|
+
| 'initializing'
|
|
74
|
+
| 'generating'
|
|
75
|
+
| 'composing'
|
|
76
|
+
| 'validating'
|
|
77
|
+
| 'completed'
|
|
78
|
+
| 'failed'
|
|
79
|
+
| 'cancelled'
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Composition plan
|
|
83
|
+
*/
|
|
84
|
+
export interface CompositionPlan {
|
|
85
|
+
/** Unique plan ID */
|
|
86
|
+
id: string
|
|
87
|
+
/** Proofs to generate */
|
|
88
|
+
proofRequests: ProofGenerationRequest[]
|
|
89
|
+
/** Providers needed */
|
|
90
|
+
requiredProviders: ProofSystem[]
|
|
91
|
+
/** Aggregation strategy */
|
|
92
|
+
strategy: ProofAggregationStrategy
|
|
93
|
+
/** Estimated total time (ms) */
|
|
94
|
+
estimatedTimeMs: number
|
|
95
|
+
/** Whether plan is valid */
|
|
96
|
+
valid: boolean
|
|
97
|
+
/** Validation errors if any */
|
|
98
|
+
errors: string[]
|
|
99
|
+
/** Recommendations */
|
|
100
|
+
recommendations: string[]
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Composition request
|
|
105
|
+
*/
|
|
106
|
+
export interface CompositionRequest {
|
|
107
|
+
/** Proof generation requests */
|
|
108
|
+
proofs: ProofGenerationRequest[]
|
|
109
|
+
/** Aggregation strategy (default: SEQUENTIAL) */
|
|
110
|
+
strategy?: ProofAggregationStrategy
|
|
111
|
+
/** Custom timeout for this request */
|
|
112
|
+
timeoutMs?: number
|
|
113
|
+
/** Abort signal */
|
|
114
|
+
abortSignal?: AbortSignal
|
|
115
|
+
/** Dry-run mode (plan without executing) */
|
|
116
|
+
dryRun?: boolean
|
|
117
|
+
/** Use template */
|
|
118
|
+
template?: string
|
|
119
|
+
/** Template parameters */
|
|
120
|
+
templateParams?: Record<string, unknown>
|
|
121
|
+
/** Custom metadata */
|
|
122
|
+
metadata?: Record<string, unknown>
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Orchestrator execution result
|
|
127
|
+
*/
|
|
128
|
+
export interface OrchestratorResult {
|
|
129
|
+
/** Whether composition succeeded */
|
|
130
|
+
success: boolean
|
|
131
|
+
/** Composed proof (if successful) */
|
|
132
|
+
composedProof?: ComposedProof
|
|
133
|
+
/** Error message (if failed) */
|
|
134
|
+
error?: string
|
|
135
|
+
/** Final state */
|
|
136
|
+
state: CompositionState
|
|
137
|
+
/** Time taken (ms) */
|
|
138
|
+
timeMs: number
|
|
139
|
+
/** Number of retries */
|
|
140
|
+
retries: number
|
|
141
|
+
/** Validation report */
|
|
142
|
+
validationReport?: ValidationReport
|
|
143
|
+
/** Audit log entries */
|
|
144
|
+
auditLog: AuditLogEntry[]
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Audit log entry
|
|
149
|
+
*/
|
|
150
|
+
export interface AuditLogEntry {
|
|
151
|
+
/** Timestamp */
|
|
152
|
+
timestamp: number
|
|
153
|
+
/** Event type */
|
|
154
|
+
event: string
|
|
155
|
+
/** Event details */
|
|
156
|
+
details: Record<string, unknown>
|
|
157
|
+
/** Duration (ms) if applicable */
|
|
158
|
+
durationMs?: number
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Progress event
|
|
163
|
+
*/
|
|
164
|
+
export interface OrchestratorProgressEvent {
|
|
165
|
+
/** Current state */
|
|
166
|
+
state: CompositionState
|
|
167
|
+
/** Progress percentage (0-100) */
|
|
168
|
+
progress: number
|
|
169
|
+
/** Current operation */
|
|
170
|
+
operation: string
|
|
171
|
+
/** Time elapsed (ms) */
|
|
172
|
+
elapsedMs: number
|
|
173
|
+
/** Estimated remaining time (ms) */
|
|
174
|
+
estimatedRemainingMs?: number
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Progress callback
|
|
179
|
+
*/
|
|
180
|
+
export type OrchestratorProgressCallback = (event: OrchestratorProgressEvent) => void
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Composition template
|
|
184
|
+
*/
|
|
185
|
+
export interface CompositionTemplate {
|
|
186
|
+
/** Template ID */
|
|
187
|
+
id: string
|
|
188
|
+
/** Template name */
|
|
189
|
+
name: string
|
|
190
|
+
/** Description */
|
|
191
|
+
description: string
|
|
192
|
+
/** Required proof types */
|
|
193
|
+
requiredProofs: {
|
|
194
|
+
circuitId: string
|
|
195
|
+
system?: ProofSystem
|
|
196
|
+
required: boolean
|
|
197
|
+
}[]
|
|
198
|
+
/** Default strategy */
|
|
199
|
+
defaultStrategy: ProofAggregationStrategy
|
|
200
|
+
/** Parameter schema */
|
|
201
|
+
parameterSchema?: Record<string, unknown>
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// ─── Default Configuration ───────────────────────────────────────────────────
|
|
205
|
+
|
|
206
|
+
export const DEFAULT_ORCHESTRATOR_CONFIG: OrchestratorConfig = {
|
|
207
|
+
maxRetries: 3,
|
|
208
|
+
baseDelayMs: 1000,
|
|
209
|
+
maxDelayMs: 30000,
|
|
210
|
+
timeoutMs: 300000, // 5 minutes
|
|
211
|
+
enableAuditLog: true,
|
|
212
|
+
dryRunDefault: false,
|
|
213
|
+
validateBeforeCompose: true,
|
|
214
|
+
strictValidation: false,
|
|
215
|
+
parallelInit: true,
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// ─── Built-in Templates ──────────────────────────────────────────────────────
|
|
219
|
+
|
|
220
|
+
export const BUILTIN_TEMPLATES: CompositionTemplate[] = [
|
|
221
|
+
{
|
|
222
|
+
id: 'shielded-transfer',
|
|
223
|
+
name: 'Shielded Transfer',
|
|
224
|
+
description: 'Standard shielded transfer with funding and validity proofs',
|
|
225
|
+
requiredProofs: [
|
|
226
|
+
{ circuitId: 'funding_proof', required: true },
|
|
227
|
+
{ circuitId: 'validity_proof', required: true },
|
|
228
|
+
],
|
|
229
|
+
defaultStrategy: Strategy.SEQUENTIAL,
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
id: 'compliant-transfer',
|
|
233
|
+
name: 'Compliant Transfer',
|
|
234
|
+
description: 'Shielded transfer with compliance proof for regulated transfers',
|
|
235
|
+
requiredProofs: [
|
|
236
|
+
{ circuitId: 'funding_proof', required: true },
|
|
237
|
+
{ circuitId: 'validity_proof', required: true },
|
|
238
|
+
{ circuitId: 'compliance_proof', required: true },
|
|
239
|
+
],
|
|
240
|
+
defaultStrategy: Strategy.SEQUENTIAL,
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
id: 'multi-chain-bridge',
|
|
244
|
+
name: 'Multi-Chain Bridge',
|
|
245
|
+
description: 'Cross-chain proof composition for bridge transfers',
|
|
246
|
+
requiredProofs: [
|
|
247
|
+
{ circuitId: 'source_chain_proof', required: true },
|
|
248
|
+
{ circuitId: 'bridge_proof', required: true },
|
|
249
|
+
{ circuitId: 'destination_chain_proof', required: true },
|
|
250
|
+
],
|
|
251
|
+
defaultStrategy: Strategy.SEQUENTIAL,
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
id: 'batch-verification',
|
|
255
|
+
name: 'Batch Verification',
|
|
256
|
+
description: 'Batch multiple proofs for efficient verification',
|
|
257
|
+
requiredProofs: [],
|
|
258
|
+
defaultStrategy: Strategy.BATCH,
|
|
259
|
+
},
|
|
260
|
+
]
|
|
261
|
+
|
|
262
|
+
// ─── Helper Functions ────────────────────────────────────────────────────────
|
|
263
|
+
|
|
264
|
+
function generateId(prefix: string): string {
|
|
265
|
+
return `${prefix}-${bytesToHex(randomBytes(8))}`
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
function delay(ms: number): Promise<void> {
|
|
269
|
+
return new Promise(resolve => setTimeout(resolve, ms))
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
function computeBackoffDelay(
|
|
273
|
+
attempt: number,
|
|
274
|
+
baseDelayMs: number,
|
|
275
|
+
maxDelayMs: number,
|
|
276
|
+
): number {
|
|
277
|
+
const exponentialDelay = baseDelayMs * Math.pow(2, attempt)
|
|
278
|
+
const jitter = Math.random() * 0.3 * exponentialDelay
|
|
279
|
+
return Math.min(exponentialDelay + jitter, maxDelayMs)
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// ─── Proof Orchestrator ──────────────────────────────────────────────────────
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* ProofOrchestrator
|
|
286
|
+
*
|
|
287
|
+
* High-level orchestrator for proof composition workflows.
|
|
288
|
+
*
|
|
289
|
+
* @example
|
|
290
|
+
* ```typescript
|
|
291
|
+
* const orchestrator = new ProofOrchestrator()
|
|
292
|
+
*
|
|
293
|
+
* // Register providers
|
|
294
|
+
* orchestrator.registerProvider(noirProvider)
|
|
295
|
+
* orchestrator.registerProvider(halo2Provider)
|
|
296
|
+
*
|
|
297
|
+
* // Plan composition
|
|
298
|
+
* const plan = await orchestrator.plan({
|
|
299
|
+
* proofs: [
|
|
300
|
+
* { circuitId: 'funding_proof', ... },
|
|
301
|
+
* { circuitId: 'validity_proof', ... },
|
|
302
|
+
* ],
|
|
303
|
+
* strategy: ProofAggregationStrategy.SEQUENTIAL,
|
|
304
|
+
* })
|
|
305
|
+
*
|
|
306
|
+
* // Execute composition
|
|
307
|
+
* const result = await orchestrator.execute({
|
|
308
|
+
* proofs: [...],
|
|
309
|
+
* onProgress: (event) => console.log(event),
|
|
310
|
+
* })
|
|
311
|
+
* ```
|
|
312
|
+
*/
|
|
313
|
+
export class ProofOrchestrator {
|
|
314
|
+
private _config: OrchestratorConfig
|
|
315
|
+
private _providers: Map<ProofSystem, ComposableProofProvider> = new Map()
|
|
316
|
+
private _templates: Map<string, CompositionTemplate> = new Map()
|
|
317
|
+
private _validator: CrossSystemValidator
|
|
318
|
+
private _state: CompositionState = 'idle'
|
|
319
|
+
private _auditLog: AuditLogEntry[] = []
|
|
320
|
+
private _currentAbortController?: AbortController
|
|
321
|
+
|
|
322
|
+
constructor(config?: Partial<OrchestratorConfig>) {
|
|
323
|
+
this._config = { ...DEFAULT_ORCHESTRATOR_CONFIG, ...config }
|
|
324
|
+
this._validator = new CrossSystemValidator({
|
|
325
|
+
strictMode: this._config.strictValidation,
|
|
326
|
+
})
|
|
327
|
+
|
|
328
|
+
// Register built-in templates
|
|
329
|
+
for (const template of BUILTIN_TEMPLATES) {
|
|
330
|
+
this._templates.set(template.id, template)
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// ─── Configuration ─────────────────────────────────────────────────────────
|
|
335
|
+
|
|
336
|
+
get config(): OrchestratorConfig {
|
|
337
|
+
return { ...this._config }
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
get state(): CompositionState {
|
|
341
|
+
return this._state
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
updateConfig(config: Partial<OrchestratorConfig>): void {
|
|
345
|
+
this._config = { ...this._config, ...config }
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// ─── Provider Management ───────────────────────────────────────────────────
|
|
349
|
+
|
|
350
|
+
registerProvider(provider: ComposableProofProvider): void {
|
|
351
|
+
this._providers.set(provider.system, provider)
|
|
352
|
+
this._log('provider_registered', { system: provider.system })
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
unregisterProvider(system: ProofSystem): boolean {
|
|
356
|
+
const removed = this._providers.delete(system)
|
|
357
|
+
if (removed) {
|
|
358
|
+
this._log('provider_unregistered', { system })
|
|
359
|
+
}
|
|
360
|
+
return removed
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
getProvider(system: ProofSystem): ComposableProofProvider | undefined {
|
|
364
|
+
return this._providers.get(system)
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
getAvailableSystems(): ProofSystem[] {
|
|
368
|
+
return Array.from(this._providers.keys())
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// ─── Template Management ───────────────────────────────────────────────────
|
|
372
|
+
|
|
373
|
+
registerTemplate(template: CompositionTemplate): void {
|
|
374
|
+
this._templates.set(template.id, template)
|
|
375
|
+
this._log('template_registered', { templateId: template.id })
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
getTemplate(id: string): CompositionTemplate | undefined {
|
|
379
|
+
return this._templates.get(id)
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
getTemplates(): CompositionTemplate[] {
|
|
383
|
+
return Array.from(this._templates.values())
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// ─── Planning ──────────────────────────────────────────────────────────────
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Create a composition plan without executing
|
|
390
|
+
*/
|
|
391
|
+
async plan(request: CompositionRequest): Promise<CompositionPlan> {
|
|
392
|
+
const startTime = Date.now()
|
|
393
|
+
this._setState('planning')
|
|
394
|
+
|
|
395
|
+
const planId = generateId('plan')
|
|
396
|
+
const errors: string[] = []
|
|
397
|
+
const recommendations: string[] = []
|
|
398
|
+
|
|
399
|
+
// Apply template if specified
|
|
400
|
+
const proofRequests = [...request.proofs]
|
|
401
|
+
let strategy = request.strategy || Strategy.SEQUENTIAL
|
|
402
|
+
|
|
403
|
+
if (request.template) {
|
|
404
|
+
const template = this._templates.get(request.template)
|
|
405
|
+
if (!template) {
|
|
406
|
+
errors.push(`Template '${request.template}' not found`)
|
|
407
|
+
} else {
|
|
408
|
+
strategy = template.defaultStrategy
|
|
409
|
+
// Merge template requirements with provided proofs
|
|
410
|
+
for (const req of template.requiredProofs) {
|
|
411
|
+
const hasProof = proofRequests.some(p => p.circuitId === req.circuitId)
|
|
412
|
+
if (!hasProof && req.required) {
|
|
413
|
+
errors.push(`Required proof '${req.circuitId}' from template not provided`)
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
// Determine required providers
|
|
420
|
+
const requiredProviders = new Set<ProofSystem>()
|
|
421
|
+
for (const proof of proofRequests) {
|
|
422
|
+
const system = proof.system || this._inferSystem(proof.circuitId)
|
|
423
|
+
if (system) {
|
|
424
|
+
requiredProviders.add(system)
|
|
425
|
+
} else {
|
|
426
|
+
errors.push(`Cannot determine system for circuit '${proof.circuitId}'`)
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// Check provider availability
|
|
431
|
+
for (const system of requiredProviders) {
|
|
432
|
+
if (!this._providers.has(system)) {
|
|
433
|
+
errors.push(`No provider registered for system '${system}'`)
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
// Estimate time
|
|
438
|
+
let estimatedTimeMs = 0
|
|
439
|
+
for (const system of requiredProviders) {
|
|
440
|
+
const provider = this._providers.get(system)
|
|
441
|
+
if (provider) {
|
|
442
|
+
estimatedTimeMs += provider.capabilities.maxProofSize > 0 ? 5000 : 10000
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
estimatedTimeMs *= proofRequests.length
|
|
446
|
+
|
|
447
|
+
// Generate recommendations
|
|
448
|
+
if (proofRequests.length > 3 && strategy === Strategy.SEQUENTIAL) {
|
|
449
|
+
recommendations.push('Consider using PARALLEL or BATCH strategy for better performance')
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
const requiredProvidersArray = Array.from(requiredProviders)
|
|
453
|
+
if (requiredProvidersArray.length > 1) {
|
|
454
|
+
const compatible = this._checkProviderCompatibility(requiredProvidersArray)
|
|
455
|
+
if (!compatible) {
|
|
456
|
+
recommendations.push('Multi-system composition detected - ensure cross-system validation')
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
this._setState('idle')
|
|
461
|
+
this._log('plan_created', {
|
|
462
|
+
planId,
|
|
463
|
+
proofCount: proofRequests.length,
|
|
464
|
+
providers: requiredProvidersArray,
|
|
465
|
+
errors: errors.length,
|
|
466
|
+
timeMs: Date.now() - startTime,
|
|
467
|
+
})
|
|
468
|
+
|
|
469
|
+
return {
|
|
470
|
+
id: planId,
|
|
471
|
+
proofRequests,
|
|
472
|
+
requiredProviders: requiredProvidersArray,
|
|
473
|
+
strategy,
|
|
474
|
+
estimatedTimeMs,
|
|
475
|
+
valid: errors.length === 0,
|
|
476
|
+
errors,
|
|
477
|
+
recommendations,
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
// ─── Execution ─────────────────────────────────────────────────────────────
|
|
482
|
+
|
|
483
|
+
/**
|
|
484
|
+
* Execute a composition request
|
|
485
|
+
*/
|
|
486
|
+
async execute(
|
|
487
|
+
request: CompositionRequest,
|
|
488
|
+
onProgress?: OrchestratorProgressCallback,
|
|
489
|
+
): Promise<OrchestratorResult> {
|
|
490
|
+
const startTime = Date.now()
|
|
491
|
+
const auditLog: AuditLogEntry[] = []
|
|
492
|
+
|
|
493
|
+
// Check for dry-run
|
|
494
|
+
if (request.dryRun ?? this._config.dryRunDefault) {
|
|
495
|
+
const plan = await this.plan(request)
|
|
496
|
+
return {
|
|
497
|
+
success: plan.valid,
|
|
498
|
+
error: plan.errors.length > 0 ? plan.errors.join('; ') : undefined,
|
|
499
|
+
state: 'completed',
|
|
500
|
+
timeMs: Date.now() - startTime,
|
|
501
|
+
retries: 0,
|
|
502
|
+
auditLog,
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
// Setup abort handling
|
|
507
|
+
this._currentAbortController = new AbortController()
|
|
508
|
+
const combinedSignal = request.abortSignal
|
|
509
|
+
? this._combineAbortSignals(request.abortSignal, this._currentAbortController.signal)
|
|
510
|
+
: this._currentAbortController.signal
|
|
511
|
+
|
|
512
|
+
let retries = 0
|
|
513
|
+
let lastError: string | undefined
|
|
514
|
+
|
|
515
|
+
try {
|
|
516
|
+
while (retries <= this._config.maxRetries) {
|
|
517
|
+
try {
|
|
518
|
+
const result = await this._executeOnce(
|
|
519
|
+
request,
|
|
520
|
+
combinedSignal,
|
|
521
|
+
onProgress,
|
|
522
|
+
startTime,
|
|
523
|
+
auditLog,
|
|
524
|
+
)
|
|
525
|
+
|
|
526
|
+
if (result.success) {
|
|
527
|
+
return result
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
lastError = result.error
|
|
531
|
+
retries++
|
|
532
|
+
|
|
533
|
+
if (retries <= this._config.maxRetries) {
|
|
534
|
+
const backoffDelay = computeBackoffDelay(
|
|
535
|
+
retries - 1,
|
|
536
|
+
this._config.baseDelayMs,
|
|
537
|
+
this._config.maxDelayMs,
|
|
538
|
+
)
|
|
539
|
+
|
|
540
|
+
this._log('retry_scheduled', { attempt: retries, delayMs: backoffDelay }, auditLog)
|
|
541
|
+
|
|
542
|
+
await delay(backoffDelay)
|
|
543
|
+
|
|
544
|
+
if (combinedSignal.aborted) {
|
|
545
|
+
return this._createCancelledResult(startTime, auditLog)
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
} catch (error) {
|
|
549
|
+
lastError = error instanceof Error ? error.message : 'Unknown error'
|
|
550
|
+
retries++
|
|
551
|
+
|
|
552
|
+
if (retries > this._config.maxRetries) {
|
|
553
|
+
break
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
const backoffDelay = computeBackoffDelay(
|
|
557
|
+
retries - 1,
|
|
558
|
+
this._config.baseDelayMs,
|
|
559
|
+
this._config.maxDelayMs,
|
|
560
|
+
)
|
|
561
|
+
|
|
562
|
+
this._log('error_retry', { error: lastError, attempt: retries, delayMs: backoffDelay }, auditLog)
|
|
563
|
+
|
|
564
|
+
await delay(backoffDelay)
|
|
565
|
+
|
|
566
|
+
if (combinedSignal.aborted) {
|
|
567
|
+
return this._createCancelledResult(startTime, auditLog)
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
// All retries exhausted
|
|
573
|
+
this._setState('failed')
|
|
574
|
+
return {
|
|
575
|
+
success: false,
|
|
576
|
+
error: lastError || 'Max retries exceeded',
|
|
577
|
+
state: 'failed',
|
|
578
|
+
timeMs: Date.now() - startTime,
|
|
579
|
+
retries,
|
|
580
|
+
auditLog,
|
|
581
|
+
}
|
|
582
|
+
} finally {
|
|
583
|
+
this._currentAbortController = undefined
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
/**
|
|
588
|
+
* Cancel current composition
|
|
589
|
+
*/
|
|
590
|
+
cancel(): void {
|
|
591
|
+
if (this._currentAbortController) {
|
|
592
|
+
this._currentAbortController.abort()
|
|
593
|
+
this._setState('cancelled')
|
|
594
|
+
this._log('composition_cancelled', {})
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
// ─── Private Methods ───────────────────────────────────────────────────────
|
|
599
|
+
|
|
600
|
+
private async _executeOnce(
|
|
601
|
+
request: CompositionRequest,
|
|
602
|
+
abortSignal: AbortSignal,
|
|
603
|
+
onProgress?: OrchestratorProgressCallback,
|
|
604
|
+
startTime?: number,
|
|
605
|
+
auditLog?: AuditLogEntry[],
|
|
606
|
+
): Promise<OrchestratorResult> {
|
|
607
|
+
const start = startTime || Date.now()
|
|
608
|
+
const log = auditLog || []
|
|
609
|
+
|
|
610
|
+
// Create timeout
|
|
611
|
+
const timeoutMs = request.timeoutMs || this._config.timeoutMs
|
|
612
|
+
const timeoutPromise = new Promise<never>((_, reject) => {
|
|
613
|
+
setTimeout(() => reject(new Error('Composition timeout')), timeoutMs)
|
|
614
|
+
})
|
|
615
|
+
|
|
616
|
+
try {
|
|
617
|
+
// Planning phase
|
|
618
|
+
this._setState('planning')
|
|
619
|
+
this._reportProgress(onProgress, 'planning', 5, start)
|
|
620
|
+
this._log('execution_started', { proofCount: request.proofs.length }, log)
|
|
621
|
+
|
|
622
|
+
const plan = await this.plan(request)
|
|
623
|
+
if (!plan.valid) {
|
|
624
|
+
return {
|
|
625
|
+
success: false,
|
|
626
|
+
error: plan.errors.join('; '),
|
|
627
|
+
state: 'failed',
|
|
628
|
+
timeMs: Date.now() - start,
|
|
629
|
+
retries: 0,
|
|
630
|
+
auditLog: log,
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
if (abortSignal.aborted) {
|
|
635
|
+
return this._createCancelledResult(start, log)
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
// Initialize providers
|
|
639
|
+
this._setState('initializing')
|
|
640
|
+
this._reportProgress(onProgress, 'initializing', 15, start)
|
|
641
|
+
this._log('providers_initializing', { count: plan.requiredProviders.length }, log)
|
|
642
|
+
|
|
643
|
+
await Promise.race([
|
|
644
|
+
this._initializeProviders(plan.requiredProviders),
|
|
645
|
+
timeoutPromise,
|
|
646
|
+
])
|
|
647
|
+
|
|
648
|
+
if (abortSignal.aborted) {
|
|
649
|
+
return this._createCancelledResult(start, log)
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
// Generate proofs
|
|
653
|
+
this._setState('generating')
|
|
654
|
+
this._reportProgress(onProgress, 'generating', 30, start)
|
|
655
|
+
this._log('proof_generation_started', { count: plan.proofRequests.length }, log)
|
|
656
|
+
|
|
657
|
+
const proofs = await Promise.race([
|
|
658
|
+
this._generateProofs(plan.proofRequests, onProgress, start),
|
|
659
|
+
timeoutPromise,
|
|
660
|
+
])
|
|
661
|
+
|
|
662
|
+
if (abortSignal.aborted) {
|
|
663
|
+
return this._createCancelledResult(start, log)
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
// Validate proofs
|
|
667
|
+
let validationReport: ValidationReport | undefined
|
|
668
|
+
if (this._config.validateBeforeCompose) {
|
|
669
|
+
this._setState('validating')
|
|
670
|
+
this._reportProgress(onProgress, 'validating', 70, start)
|
|
671
|
+
this._log('validation_started', {}, log)
|
|
672
|
+
|
|
673
|
+
validationReport = this._validator.validate(proofs)
|
|
674
|
+
this._log('validation_completed', {
|
|
675
|
+
valid: validationReport.valid,
|
|
676
|
+
errors: validationReport.errorCount,
|
|
677
|
+
warnings: validationReport.warningCount,
|
|
678
|
+
}, log)
|
|
679
|
+
|
|
680
|
+
if (!validationReport.valid) {
|
|
681
|
+
return {
|
|
682
|
+
success: false,
|
|
683
|
+
error: 'Proof validation failed',
|
|
684
|
+
state: 'failed',
|
|
685
|
+
timeMs: Date.now() - start,
|
|
686
|
+
retries: 0,
|
|
687
|
+
validationReport,
|
|
688
|
+
auditLog: log,
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
if (abortSignal.aborted) {
|
|
694
|
+
return this._createCancelledResult(start, log)
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
// Compose proofs
|
|
698
|
+
this._setState('composing')
|
|
699
|
+
this._reportProgress(onProgress, 'composing', 85, start)
|
|
700
|
+
this._log('composition_started', { strategy: plan.strategy }, log)
|
|
701
|
+
|
|
702
|
+
const composedProof = await Promise.race([
|
|
703
|
+
this._composeProofs(proofs, plan.strategy),
|
|
704
|
+
timeoutPromise,
|
|
705
|
+
])
|
|
706
|
+
|
|
707
|
+
// Complete
|
|
708
|
+
this._setState('completed')
|
|
709
|
+
this._reportProgress(onProgress, 'completed', 100, start)
|
|
710
|
+
this._log('composition_completed', {
|
|
711
|
+
composedProofId: composedProof.id,
|
|
712
|
+
timeMs: Date.now() - start,
|
|
713
|
+
}, log)
|
|
714
|
+
|
|
715
|
+
return {
|
|
716
|
+
success: true,
|
|
717
|
+
composedProof,
|
|
718
|
+
state: 'completed',
|
|
719
|
+
timeMs: Date.now() - start,
|
|
720
|
+
retries: 0,
|
|
721
|
+
validationReport,
|
|
722
|
+
auditLog: log,
|
|
723
|
+
}
|
|
724
|
+
} catch (error) {
|
|
725
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error'
|
|
726
|
+
this._log('execution_error', { error: errorMessage }, log)
|
|
727
|
+
throw error
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
private async _initializeProviders(systems: ProofSystem[]): Promise<void> {
|
|
732
|
+
const initPromises = systems.map(async (system) => {
|
|
733
|
+
const provider = this._providers.get(system)
|
|
734
|
+
if (provider && !provider.status.isReady) {
|
|
735
|
+
await provider.initialize()
|
|
736
|
+
}
|
|
737
|
+
})
|
|
738
|
+
|
|
739
|
+
if (this._config.parallelInit) {
|
|
740
|
+
await Promise.all(initPromises)
|
|
741
|
+
} else {
|
|
742
|
+
for (const promise of initPromises) {
|
|
743
|
+
await promise
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
private async _generateProofs(
|
|
749
|
+
requests: ProofGenerationRequest[],
|
|
750
|
+
onProgress?: OrchestratorProgressCallback,
|
|
751
|
+
startTime?: number,
|
|
752
|
+
): Promise<SingleProof[]> {
|
|
753
|
+
const proofs: SingleProof[] = []
|
|
754
|
+
const start = startTime || Date.now()
|
|
755
|
+
|
|
756
|
+
for (let i = 0; i < requests.length; i++) {
|
|
757
|
+
const request = requests[i]
|
|
758
|
+
const system = request.system || this._inferSystem(request.circuitId)
|
|
759
|
+
|
|
760
|
+
if (!system) {
|
|
761
|
+
throw new Error(`Cannot determine system for circuit '${request.circuitId}'`)
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
const provider = this._providers.get(system)
|
|
765
|
+
if (!provider) {
|
|
766
|
+
throw new Error(`No provider for system '${system}'`)
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
const progressPercent = 30 + Math.floor((i / requests.length) * 40)
|
|
770
|
+
this._reportProgress(
|
|
771
|
+
onProgress,
|
|
772
|
+
`generating proof ${i + 1}/${requests.length}`,
|
|
773
|
+
progressPercent,
|
|
774
|
+
start,
|
|
775
|
+
)
|
|
776
|
+
|
|
777
|
+
const result = await provider.generateProof(request)
|
|
778
|
+
|
|
779
|
+
if (!result.success || !result.proof) {
|
|
780
|
+
throw new Error(result.error || 'Proof generation failed')
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
proofs.push(result.proof)
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
return proofs
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
private async _composeProofs(
|
|
790
|
+
proofs: SingleProof[],
|
|
791
|
+
strategy: ProofAggregationStrategy,
|
|
792
|
+
): Promise<ComposedProof> {
|
|
793
|
+
// Create composed proof structure
|
|
794
|
+
const composedProof: ComposedProof = {
|
|
795
|
+
id: generateId('composed'),
|
|
796
|
+
proofs,
|
|
797
|
+
strategy,
|
|
798
|
+
status: ComposedProofStatus.VERIFIED,
|
|
799
|
+
combinedPublicInputs: proofs.flatMap(p => p.publicInputs),
|
|
800
|
+
compositionMetadata: {
|
|
801
|
+
proofCount: proofs.length,
|
|
802
|
+
systems: [...new Set(proofs.map(p => p.metadata.system))],
|
|
803
|
+
compositionTimeMs: 0,
|
|
804
|
+
success: true,
|
|
805
|
+
inputHash: this._computeInputHash(proofs),
|
|
806
|
+
},
|
|
807
|
+
verificationHints: {
|
|
808
|
+
verificationOrder: proofs.map(p => p.id),
|
|
809
|
+
parallelGroups: strategy === Strategy.PARALLEL ? [proofs.map(p => p.id)] : [],
|
|
810
|
+
estimatedTimeMs: proofs.length * 100,
|
|
811
|
+
estimatedCost: BigInt(proofs.length * 1000),
|
|
812
|
+
supportsBatchVerification: strategy === Strategy.BATCH,
|
|
813
|
+
},
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
return composedProof
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
private _computeInputHash(proofs: SingleProof[]): HexString {
|
|
820
|
+
const data = proofs.map(p => p.proof).join('')
|
|
821
|
+
let hash = 0
|
|
822
|
+
for (let i = 0; i < data.length; i++) {
|
|
823
|
+
hash = ((hash << 5) - hash) + data.charCodeAt(i)
|
|
824
|
+
hash = hash & hash
|
|
825
|
+
}
|
|
826
|
+
return `0x${Math.abs(hash).toString(16).padStart(16, '0')}` as HexString
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
private _inferSystem(circuitId: string): ProofSystem | undefined {
|
|
830
|
+
// Check if any provider has this circuit
|
|
831
|
+
for (const [system, provider] of this._providers) {
|
|
832
|
+
if (provider.hasCircuit(circuitId)) {
|
|
833
|
+
return system
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
// Infer from circuit ID naming convention
|
|
838
|
+
if (circuitId.includes('noir') || circuitId.includes('funding') || circuitId.includes('validity')) {
|
|
839
|
+
return 'noir'
|
|
840
|
+
}
|
|
841
|
+
if (circuitId.includes('halo2') || circuitId.includes('orchard')) {
|
|
842
|
+
return 'halo2'
|
|
843
|
+
}
|
|
844
|
+
if (circuitId.includes('kimchi') || circuitId.includes('mina')) {
|
|
845
|
+
return 'kimchi'
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
return undefined
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
private _checkProviderCompatibility(systems: ProofSystem[]): boolean {
|
|
852
|
+
for (let i = 0; i < systems.length; i++) {
|
|
853
|
+
for (let j = i + 1; j < systems.length; j++) {
|
|
854
|
+
if (!this._validator.areSystemsCompatible(systems[i], systems[j])) {
|
|
855
|
+
return false
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
return true
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
private _setState(state: CompositionState): void {
|
|
863
|
+
this._state = state
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
private _reportProgress(
|
|
867
|
+
callback: OrchestratorProgressCallback | undefined,
|
|
868
|
+
operation: string,
|
|
869
|
+
progress: number,
|
|
870
|
+
startTime: number,
|
|
871
|
+
): void {
|
|
872
|
+
if (callback) {
|
|
873
|
+
const elapsedMs = Date.now() - startTime
|
|
874
|
+
const estimatedRemainingMs = progress > 0
|
|
875
|
+
? Math.floor((elapsedMs / progress) * (100 - progress))
|
|
876
|
+
: undefined
|
|
877
|
+
|
|
878
|
+
callback({
|
|
879
|
+
state: this._state,
|
|
880
|
+
progress,
|
|
881
|
+
operation,
|
|
882
|
+
elapsedMs,
|
|
883
|
+
estimatedRemainingMs,
|
|
884
|
+
})
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
private _log(
|
|
889
|
+
event: string,
|
|
890
|
+
details: Record<string, unknown>,
|
|
891
|
+
targetLog?: AuditLogEntry[],
|
|
892
|
+
): void {
|
|
893
|
+
if (!this._config.enableAuditLog) return
|
|
894
|
+
|
|
895
|
+
const entry: AuditLogEntry = {
|
|
896
|
+
timestamp: Date.now(),
|
|
897
|
+
event,
|
|
898
|
+
details,
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
this._auditLog.push(entry)
|
|
902
|
+
if (targetLog) {
|
|
903
|
+
targetLog.push(entry)
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
private _combineAbortSignals(signal1: AbortSignal, signal2: AbortSignal): AbortSignal {
|
|
908
|
+
const controller = new AbortController()
|
|
909
|
+
|
|
910
|
+
const onAbort = () => controller.abort()
|
|
911
|
+
|
|
912
|
+
signal1.addEventListener('abort', onAbort)
|
|
913
|
+
signal2.addEventListener('abort', onAbort)
|
|
914
|
+
|
|
915
|
+
if (signal1.aborted || signal2.aborted) {
|
|
916
|
+
controller.abort()
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
return controller.signal
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
private _createCancelledResult(startTime: number, auditLog: AuditLogEntry[]): OrchestratorResult {
|
|
923
|
+
this._setState('cancelled')
|
|
924
|
+
return {
|
|
925
|
+
success: false,
|
|
926
|
+
error: 'Composition cancelled',
|
|
927
|
+
state: 'cancelled',
|
|
928
|
+
timeMs: Date.now() - startTime,
|
|
929
|
+
retries: 0,
|
|
930
|
+
auditLog,
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
// ─── Audit Log Access ──────────────────────────────────────────────────────
|
|
935
|
+
|
|
936
|
+
/**
|
|
937
|
+
* Get full audit log
|
|
938
|
+
*/
|
|
939
|
+
getAuditLog(): AuditLogEntry[] {
|
|
940
|
+
return [...this._auditLog]
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
/**
|
|
944
|
+
* Clear audit log
|
|
945
|
+
*/
|
|
946
|
+
clearAuditLog(): void {
|
|
947
|
+
this._auditLog = []
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
|
|
951
|
+
// ─── Factory Function ────────────────────────────────────────────────────────
|
|
952
|
+
|
|
953
|
+
/**
|
|
954
|
+
* Create a proof orchestrator with optional configuration
|
|
955
|
+
*/
|
|
956
|
+
export function createProofOrchestrator(
|
|
957
|
+
config?: Partial<OrchestratorConfig>,
|
|
958
|
+
): ProofOrchestrator {
|
|
959
|
+
return new ProofOrchestrator(config)
|
|
960
|
+
}
|