@sip-protocol/sdk 0.7.2 → 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 +48874 -18336
- package/dist/browser.mjs +674 -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-YWGJ77A2.mjs +33806 -0
- 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-DXh2IGkz.d.ts +24681 -0
- package/dist/index-DeE1ZzA4.d.mts +24681 -0
- package/dist/index.d.mts +9 -3
- package/dist/index.d.ts +9 -3
- package/dist/index.js +48676 -17318
- package/dist/index.mjs +583 -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 +276 -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 +201 -0
- 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 +402 -0
- package/src/chains/solana/providers/index.ts +85 -0
- package/src/chains/solana/providers/interface.ts +221 -0
- 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 +790 -0
- package/src/chains/solana/rpc-client.ts +1150 -0
- package/src/chains/solana/scan.ts +170 -73
- 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 +77 -7
- 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 +37 -0
- package/src/compliance/range-sas.ts +956 -0
- 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 +785 -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 +336 -0
- package/src/privacy-backends/interface.ts +906 -0
- 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-types.ts +278 -0
- package/src/privacy-backends/privacycash.ts +456 -0
- package/src/privacy-backends/private-swap.ts +570 -0
- package/src/privacy-backends/rate-limiter.ts +683 -0
- package/src/privacy-backends/registry.ts +690 -0
- package/src/privacy-backends/router.ts +626 -0
- package/src/privacy-backends/shadowwire.ts +449 -0
- package/src/privacy-backends/sip-native.ts +256 -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 +111 -30
- 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/surveillance/algorithms/address-reuse.ts +143 -0
- package/src/surveillance/algorithms/cluster.ts +247 -0
- package/src/surveillance/algorithms/exchange.ts +295 -0
- package/src/surveillance/algorithms/temporal.ts +337 -0
- package/src/surveillance/analyzer.ts +442 -0
- package/src/surveillance/index.ts +64 -0
- package/src/surveillance/scoring.ts +372 -0
- package/src/surveillance/types.ts +264 -0
- 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-3INS3PR5.mjs +0 -884
- package/dist/chunk-3OVABDRH.mjs +0 -17096
- package/dist/chunk-DLDWZFYC.mjs +0 -1495
- package/dist/chunk-E6SZWREQ.mjs +0 -57
- package/dist/chunk-G33LB27A.mjs +0 -16166
- package/dist/chunk-HGU6HZRC.mjs +0 -231
- package/dist/chunk-L2K34JCU.mjs +0 -1496
- package/dist/chunk-SN4ZDTVW.mjs +0 -16166
- package/dist/constants-VOI7BSLK.mjs +0 -27
- 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-xbWjohNq.d.mts +0 -11390
- package/dist/solana-5EMCTPTS.mjs +0 -46
- package/dist/solana-Q4NAVBTS.mjs +0 -46
|
@@ -0,0 +1,602 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dependency Graph Analyzer for Parallel Proof Generation
|
|
3
|
+
*
|
|
4
|
+
* @module proofs/parallel/dependency-graph
|
|
5
|
+
* @description Analyzes proof dependencies and determines optimal execution order
|
|
6
|
+
*
|
|
7
|
+
* M20-12: Optimize proof generation parallelization (#307)
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type {
|
|
11
|
+
DependencyNode,
|
|
12
|
+
DependencyEdge,
|
|
13
|
+
DependencyGraph,
|
|
14
|
+
GraphAnalysis,
|
|
15
|
+
IDependencyAnalyzer,
|
|
16
|
+
} from './interface'
|
|
17
|
+
|
|
18
|
+
// ─── Dependency Analyzer Implementation ──────────────────────────────────────
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Analyzes proof dependencies and builds execution graphs
|
|
22
|
+
*/
|
|
23
|
+
export class DependencyAnalyzer implements IDependencyAnalyzer {
|
|
24
|
+
/**
|
|
25
|
+
* Analyze a set of proof requests and build dependency graph
|
|
26
|
+
*/
|
|
27
|
+
analyze(nodes: DependencyNode[]): GraphAnalysis {
|
|
28
|
+
// Build the graph
|
|
29
|
+
const nodeMap = new Map<string, DependencyNode>()
|
|
30
|
+
const edges: DependencyEdge[] = []
|
|
31
|
+
const inDegree = new Map<string, number>()
|
|
32
|
+
const outDegree = new Map<string, number>()
|
|
33
|
+
|
|
34
|
+
// Index all nodes
|
|
35
|
+
for (const node of nodes) {
|
|
36
|
+
nodeMap.set(node.id, node)
|
|
37
|
+
inDegree.set(node.id, 0)
|
|
38
|
+
outDegree.set(node.id, 0)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Build edges and calculate degrees
|
|
42
|
+
for (const node of nodes) {
|
|
43
|
+
for (const depId of node.dependencies) {
|
|
44
|
+
if (nodeMap.has(depId)) {
|
|
45
|
+
edges.push({
|
|
46
|
+
from: depId,
|
|
47
|
+
to: node.id,
|
|
48
|
+
connectionType: 'proof', // Default connection type
|
|
49
|
+
})
|
|
50
|
+
inDegree.set(node.id, (inDegree.get(node.id) ?? 0) + 1)
|
|
51
|
+
outDegree.set(depId, (outDegree.get(depId) ?? 0) + 1)
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Find roots (no incoming edges)
|
|
57
|
+
const roots: string[] = []
|
|
58
|
+
for (const [id, degree] of inDegree) {
|
|
59
|
+
if (degree === 0) {
|
|
60
|
+
roots.push(id)
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Find leaves (no outgoing edges)
|
|
65
|
+
const leaves: string[] = []
|
|
66
|
+
for (const [id, degree] of outDegree) {
|
|
67
|
+
if (degree === 0) {
|
|
68
|
+
leaves.push(id)
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Detect cycles using DFS
|
|
73
|
+
const cycleResult = this.detectCycles(nodeMap, edges)
|
|
74
|
+
|
|
75
|
+
// Calculate depths and find critical path
|
|
76
|
+
const depths = this.calculateDepths(nodeMap, edges)
|
|
77
|
+
const maxDepth = Math.max(0, ...Array.from(depths.values()))
|
|
78
|
+
|
|
79
|
+
// Find critical path (longest weighted path)
|
|
80
|
+
const criticalPath = this.findCriticalPath(nodeMap, edges, depths)
|
|
81
|
+
|
|
82
|
+
// Calculate total cost
|
|
83
|
+
let totalCost = 0
|
|
84
|
+
for (const node of nodes) {
|
|
85
|
+
totalCost += node.estimatedCost
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const graph: DependencyGraph = {
|
|
89
|
+
nodes: nodeMap,
|
|
90
|
+
edges,
|
|
91
|
+
roots,
|
|
92
|
+
leaves,
|
|
93
|
+
maxDepth,
|
|
94
|
+
totalCost,
|
|
95
|
+
criticalPath,
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Calculate execution levels
|
|
99
|
+
const executionLevels = this.calculateExecutionLevels(graph)
|
|
100
|
+
|
|
101
|
+
// Find bottlenecks (high cost nodes on critical path)
|
|
102
|
+
const bottlenecks = this.findBottlenecks(graph, criticalPath)
|
|
103
|
+
|
|
104
|
+
// Suggest parallelism based on graph structure
|
|
105
|
+
const suggestedParallelism = this.suggestParallelism(graph, executionLevels)
|
|
106
|
+
|
|
107
|
+
return {
|
|
108
|
+
graph,
|
|
109
|
+
suggestedParallelism,
|
|
110
|
+
executionLevels,
|
|
111
|
+
hasCycles: cycleResult.hasCycles,
|
|
112
|
+
cyclePath: cycleResult.cyclePath,
|
|
113
|
+
bottlenecks,
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Add a node to an existing graph
|
|
119
|
+
*/
|
|
120
|
+
addNode(graph: DependencyGraph, node: DependencyNode): DependencyGraph {
|
|
121
|
+
const newNodes = new Map(graph.nodes)
|
|
122
|
+
newNodes.set(node.id, node)
|
|
123
|
+
|
|
124
|
+
// Add edges for dependencies
|
|
125
|
+
const newEdges = [...graph.edges]
|
|
126
|
+
for (const depId of node.dependencies) {
|
|
127
|
+
if (newNodes.has(depId)) {
|
|
128
|
+
newEdges.push({
|
|
129
|
+
from: depId,
|
|
130
|
+
to: node.id,
|
|
131
|
+
connectionType: 'proof',
|
|
132
|
+
})
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Recalculate graph properties
|
|
137
|
+
const roots = this.calculateRoots(newNodes, newEdges)
|
|
138
|
+
const leaves = this.calculateLeaves(newNodes, newEdges)
|
|
139
|
+
const depths = this.calculateDepths(newNodes, newEdges)
|
|
140
|
+
const maxDepth = Math.max(0, ...Array.from(depths.values()))
|
|
141
|
+
const criticalPath = this.findCriticalPath(newNodes, newEdges, depths)
|
|
142
|
+
|
|
143
|
+
let totalCost = 0
|
|
144
|
+
for (const n of newNodes.values()) {
|
|
145
|
+
totalCost += n.estimatedCost
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return {
|
|
149
|
+
nodes: newNodes,
|
|
150
|
+
edges: newEdges,
|
|
151
|
+
roots,
|
|
152
|
+
leaves,
|
|
153
|
+
maxDepth,
|
|
154
|
+
totalCost,
|
|
155
|
+
criticalPath,
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Remove a node from the graph
|
|
161
|
+
*/
|
|
162
|
+
removeNode(graph: DependencyGraph, nodeId: string): DependencyGraph {
|
|
163
|
+
const newNodes = new Map(graph.nodes)
|
|
164
|
+
newNodes.delete(nodeId)
|
|
165
|
+
|
|
166
|
+
// Remove edges involving this node
|
|
167
|
+
const newEdges = graph.edges.filter((e) => e.from !== nodeId && e.to !== nodeId)
|
|
168
|
+
|
|
169
|
+
// Recalculate graph properties
|
|
170
|
+
const roots = this.calculateRoots(newNodes, newEdges)
|
|
171
|
+
const leaves = this.calculateLeaves(newNodes, newEdges)
|
|
172
|
+
const depths = this.calculateDepths(newNodes, newEdges)
|
|
173
|
+
const maxDepth = Math.max(0, ...Array.from(depths.values()))
|
|
174
|
+
const criticalPath = this.findCriticalPath(newNodes, newEdges, depths)
|
|
175
|
+
|
|
176
|
+
let totalCost = 0
|
|
177
|
+
for (const n of newNodes.values()) {
|
|
178
|
+
totalCost += n.estimatedCost
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return {
|
|
182
|
+
nodes: newNodes,
|
|
183
|
+
edges: newEdges,
|
|
184
|
+
roots,
|
|
185
|
+
leaves,
|
|
186
|
+
maxDepth,
|
|
187
|
+
totalCost,
|
|
188
|
+
criticalPath,
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Get execution order respecting dependencies (topological sort)
|
|
194
|
+
*/
|
|
195
|
+
getExecutionOrder(graph: DependencyGraph): readonly string[] {
|
|
196
|
+
const result: string[] = []
|
|
197
|
+
const visited = new Set<string>()
|
|
198
|
+
const inProgress = new Set<string>()
|
|
199
|
+
|
|
200
|
+
const visit = (nodeId: string): boolean => {
|
|
201
|
+
if (inProgress.has(nodeId)) {
|
|
202
|
+
// Cycle detected
|
|
203
|
+
return false
|
|
204
|
+
}
|
|
205
|
+
if (visited.has(nodeId)) {
|
|
206
|
+
return true
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
inProgress.add(nodeId)
|
|
210
|
+
const node = graph.nodes.get(nodeId)
|
|
211
|
+
if (node) {
|
|
212
|
+
for (const depId of node.dependencies) {
|
|
213
|
+
if (graph.nodes.has(depId)) {
|
|
214
|
+
if (!visit(depId)) {
|
|
215
|
+
return false
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
inProgress.delete(nodeId)
|
|
221
|
+
visited.add(nodeId)
|
|
222
|
+
result.push(nodeId)
|
|
223
|
+
return true
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
for (const nodeId of graph.nodes.keys()) {
|
|
227
|
+
if (!visited.has(nodeId)) {
|
|
228
|
+
visit(nodeId)
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return result
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Find nodes ready to execute (all dependencies satisfied)
|
|
237
|
+
*/
|
|
238
|
+
getReadyNodes(graph: DependencyGraph, completed: Set<string>): readonly string[] {
|
|
239
|
+
const ready: string[] = []
|
|
240
|
+
|
|
241
|
+
for (const [nodeId, node] of graph.nodes) {
|
|
242
|
+
if (completed.has(nodeId)) {
|
|
243
|
+
continue
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Check if all dependencies are satisfied
|
|
247
|
+
let allDependenciesSatisfied = true
|
|
248
|
+
for (const depId of node.dependencies) {
|
|
249
|
+
if (graph.nodes.has(depId) && !completed.has(depId)) {
|
|
250
|
+
allDependenciesSatisfied = false
|
|
251
|
+
break
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
if (allDependenciesSatisfied) {
|
|
256
|
+
ready.push(nodeId)
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// Sort by priority (higher first), then by cost (lower first for better parallelism)
|
|
261
|
+
ready.sort((a, b) => {
|
|
262
|
+
const nodeA = graph.nodes.get(a)!
|
|
263
|
+
const nodeB = graph.nodes.get(b)!
|
|
264
|
+
const priorityDiff = (nodeB.priority ?? 0) - (nodeA.priority ?? 0)
|
|
265
|
+
if (priorityDiff !== 0) return priorityDiff
|
|
266
|
+
return nodeA.estimatedCost - nodeB.estimatedCost
|
|
267
|
+
})
|
|
268
|
+
|
|
269
|
+
return ready
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Validate graph is acyclic
|
|
274
|
+
*/
|
|
275
|
+
validateAcyclic(graph: DependencyGraph): boolean {
|
|
276
|
+
const result = this.detectCycles(graph.nodes, graph.edges)
|
|
277
|
+
return !result.hasCycles
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// ─── Private Helper Methods ──────────────────────────────────────────────────
|
|
281
|
+
|
|
282
|
+
private detectCycles(
|
|
283
|
+
nodes: Map<string, DependencyNode>,
|
|
284
|
+
edges: DependencyEdge[]
|
|
285
|
+
): { hasCycles: boolean; cyclePath?: string[] } {
|
|
286
|
+
const visited = new Set<string>()
|
|
287
|
+
const recursionStack = new Set<string>()
|
|
288
|
+
const path: string[] = []
|
|
289
|
+
|
|
290
|
+
// Build adjacency list
|
|
291
|
+
const adjacency = new Map<string, string[]>()
|
|
292
|
+
for (const node of nodes.keys()) {
|
|
293
|
+
adjacency.set(node, [])
|
|
294
|
+
}
|
|
295
|
+
for (const edge of edges) {
|
|
296
|
+
adjacency.get(edge.from)?.push(edge.to)
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
const dfs = (nodeId: string): boolean => {
|
|
300
|
+
visited.add(nodeId)
|
|
301
|
+
recursionStack.add(nodeId)
|
|
302
|
+
path.push(nodeId)
|
|
303
|
+
|
|
304
|
+
for (const neighbor of adjacency.get(nodeId) ?? []) {
|
|
305
|
+
if (!visited.has(neighbor)) {
|
|
306
|
+
if (dfs(neighbor)) {
|
|
307
|
+
return true
|
|
308
|
+
}
|
|
309
|
+
} else if (recursionStack.has(neighbor)) {
|
|
310
|
+
// Found cycle
|
|
311
|
+
path.push(neighbor)
|
|
312
|
+
return true
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
recursionStack.delete(nodeId)
|
|
317
|
+
path.pop()
|
|
318
|
+
return false
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
for (const nodeId of nodes.keys()) {
|
|
322
|
+
if (!visited.has(nodeId)) {
|
|
323
|
+
if (dfs(nodeId)) {
|
|
324
|
+
// Extract cycle from path
|
|
325
|
+
const cycleStart = path.indexOf(path[path.length - 1])
|
|
326
|
+
const cyclePath = path.slice(cycleStart)
|
|
327
|
+
return { hasCycles: true, cyclePath }
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
return { hasCycles: false }
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
private calculateDepths(
|
|
336
|
+
nodes: Map<string, DependencyNode>,
|
|
337
|
+
edges: DependencyEdge[]
|
|
338
|
+
): Map<string, number> {
|
|
339
|
+
const depths = new Map<string, number>()
|
|
340
|
+
const inDegree = new Map<string, number>()
|
|
341
|
+
|
|
342
|
+
// Initialize
|
|
343
|
+
for (const nodeId of nodes.keys()) {
|
|
344
|
+
depths.set(nodeId, 0)
|
|
345
|
+
inDegree.set(nodeId, 0)
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// Count in-degrees
|
|
349
|
+
for (const edge of edges) {
|
|
350
|
+
inDegree.set(edge.to, (inDegree.get(edge.to) ?? 0) + 1)
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// BFS from roots
|
|
354
|
+
const queue: string[] = []
|
|
355
|
+
for (const [nodeId, degree] of inDegree) {
|
|
356
|
+
if (degree === 0) {
|
|
357
|
+
queue.push(nodeId)
|
|
358
|
+
depths.set(nodeId, 0)
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
while (queue.length > 0) {
|
|
363
|
+
const current = queue.shift()!
|
|
364
|
+
const currentDepth = depths.get(current) ?? 0
|
|
365
|
+
|
|
366
|
+
for (const edge of edges) {
|
|
367
|
+
if (edge.from === current) {
|
|
368
|
+
const newDepth = Math.max(depths.get(edge.to) ?? 0, currentDepth + 1)
|
|
369
|
+
depths.set(edge.to, newDepth)
|
|
370
|
+
|
|
371
|
+
const newInDegree = (inDegree.get(edge.to) ?? 1) - 1
|
|
372
|
+
inDegree.set(edge.to, newInDegree)
|
|
373
|
+
|
|
374
|
+
if (newInDegree === 0) {
|
|
375
|
+
queue.push(edge.to)
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
return depths
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
private findCriticalPath(
|
|
385
|
+
nodes: Map<string, DependencyNode>,
|
|
386
|
+
edges: DependencyEdge[],
|
|
387
|
+
depths: Map<string, number>
|
|
388
|
+
): readonly string[] {
|
|
389
|
+
if (nodes.size === 0) {
|
|
390
|
+
return []
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
// Build reverse adjacency (to traverse backwards from leaves)
|
|
394
|
+
const reverseAdj = new Map<string, string[]>()
|
|
395
|
+
for (const nodeId of nodes.keys()) {
|
|
396
|
+
reverseAdj.set(nodeId, [])
|
|
397
|
+
}
|
|
398
|
+
for (const edge of edges) {
|
|
399
|
+
reverseAdj.get(edge.to)?.push(edge.from)
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// Calculate cumulative cost from each node to any leaf
|
|
403
|
+
const costToLeaf = new Map<string, number>()
|
|
404
|
+
const pathToLeaf = new Map<string, string[]>()
|
|
405
|
+
|
|
406
|
+
// Find leaves
|
|
407
|
+
const outDegree = new Map<string, number>()
|
|
408
|
+
for (const nodeId of nodes.keys()) {
|
|
409
|
+
outDegree.set(nodeId, 0)
|
|
410
|
+
}
|
|
411
|
+
for (const edge of edges) {
|
|
412
|
+
outDegree.set(edge.from, (outDegree.get(edge.from) ?? 0) + 1)
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
const leaves: string[] = []
|
|
416
|
+
for (const [nodeId, degree] of outDegree) {
|
|
417
|
+
if (degree === 0) {
|
|
418
|
+
leaves.push(nodeId)
|
|
419
|
+
const node = nodes.get(nodeId)!
|
|
420
|
+
costToLeaf.set(nodeId, node.estimatedCost)
|
|
421
|
+
pathToLeaf.set(nodeId, [nodeId])
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
// Process nodes in reverse topological order
|
|
426
|
+
const sortedNodes = Array.from(nodes.keys()).sort(
|
|
427
|
+
(a, b) => (depths.get(b) ?? 0) - (depths.get(a) ?? 0)
|
|
428
|
+
)
|
|
429
|
+
|
|
430
|
+
for (const nodeId of sortedNodes) {
|
|
431
|
+
if (costToLeaf.has(nodeId)) continue
|
|
432
|
+
|
|
433
|
+
const node = nodes.get(nodeId)!
|
|
434
|
+
let maxCost = 0
|
|
435
|
+
let bestPath: string[] = [nodeId]
|
|
436
|
+
|
|
437
|
+
// Find successor with maximum cost to leaf
|
|
438
|
+
for (const edge of edges) {
|
|
439
|
+
if (edge.from === nodeId) {
|
|
440
|
+
const successorCost = costToLeaf.get(edge.to) ?? 0
|
|
441
|
+
if (successorCost > maxCost) {
|
|
442
|
+
maxCost = successorCost
|
|
443
|
+
bestPath = [nodeId, ...(pathToLeaf.get(edge.to) ?? [])]
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
costToLeaf.set(nodeId, node.estimatedCost + maxCost)
|
|
449
|
+
pathToLeaf.set(nodeId, bestPath)
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
// Find root with maximum cost to leaf
|
|
453
|
+
let maxTotalCost = 0
|
|
454
|
+
let criticalPath: string[] = []
|
|
455
|
+
|
|
456
|
+
for (const nodeId of nodes.keys()) {
|
|
457
|
+
const inDeg = edges.filter((e) => e.to === nodeId).length
|
|
458
|
+
if (inDeg === 0) {
|
|
459
|
+
const totalCost = costToLeaf.get(nodeId) ?? 0
|
|
460
|
+
if (totalCost > maxTotalCost) {
|
|
461
|
+
maxTotalCost = totalCost
|
|
462
|
+
criticalPath = pathToLeaf.get(nodeId) ?? []
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
return criticalPath
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
private calculateExecutionLevels(graph: DependencyGraph): readonly string[][] {
|
|
471
|
+
const levels: string[][] = []
|
|
472
|
+
const completed = new Set<string>()
|
|
473
|
+
|
|
474
|
+
while (completed.size < graph.nodes.size) {
|
|
475
|
+
const ready = this.getReadyNodes(graph, completed)
|
|
476
|
+
if (ready.length === 0) {
|
|
477
|
+
// No more nodes ready (cycle or all done)
|
|
478
|
+
break
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
levels.push([...ready])
|
|
482
|
+
for (const nodeId of ready) {
|
|
483
|
+
completed.add(nodeId)
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
return levels
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
private findBottlenecks(graph: DependencyGraph, criticalPath: readonly string[]): readonly string[] {
|
|
491
|
+
if (criticalPath.length === 0) {
|
|
492
|
+
return []
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
// Calculate average cost
|
|
496
|
+
let totalCost = 0
|
|
497
|
+
for (const node of graph.nodes.values()) {
|
|
498
|
+
totalCost += node.estimatedCost
|
|
499
|
+
}
|
|
500
|
+
const avgCost = totalCost / graph.nodes.size
|
|
501
|
+
|
|
502
|
+
// Bottlenecks are critical path nodes with above-average cost
|
|
503
|
+
const bottlenecks: string[] = []
|
|
504
|
+
for (const nodeId of criticalPath) {
|
|
505
|
+
const node = graph.nodes.get(nodeId)
|
|
506
|
+
if (node && node.estimatedCost > avgCost * 1.5) {
|
|
507
|
+
bottlenecks.push(nodeId)
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
return bottlenecks
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
private suggestParallelism(_graph: DependencyGraph, levels: readonly string[][]): number {
|
|
515
|
+
if (levels.length === 0) {
|
|
516
|
+
return 1
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
// Suggested parallelism is the maximum level width
|
|
520
|
+
let maxWidth = 1
|
|
521
|
+
for (const level of levels) {
|
|
522
|
+
maxWidth = Math.max(maxWidth, level.length)
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
// Cap at reasonable maximum
|
|
526
|
+
return Math.min(maxWidth, 8)
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
private calculateRoots(
|
|
530
|
+
nodes: Map<string, DependencyNode>,
|
|
531
|
+
edges: DependencyEdge[]
|
|
532
|
+
): readonly string[] {
|
|
533
|
+
const hasIncoming = new Set<string>()
|
|
534
|
+
for (const edge of edges) {
|
|
535
|
+
hasIncoming.add(edge.to)
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
const roots: string[] = []
|
|
539
|
+
for (const nodeId of nodes.keys()) {
|
|
540
|
+
if (!hasIncoming.has(nodeId)) {
|
|
541
|
+
roots.push(nodeId)
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
return roots
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
private calculateLeaves(
|
|
549
|
+
nodes: Map<string, DependencyNode>,
|
|
550
|
+
edges: DependencyEdge[]
|
|
551
|
+
): readonly string[] {
|
|
552
|
+
const hasOutgoing = new Set<string>()
|
|
553
|
+
for (const edge of edges) {
|
|
554
|
+
hasOutgoing.add(edge.from)
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
const leaves: string[] = []
|
|
558
|
+
for (const nodeId of nodes.keys()) {
|
|
559
|
+
if (!hasOutgoing.has(nodeId)) {
|
|
560
|
+
leaves.push(nodeId)
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
return leaves
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
/**
|
|
569
|
+
* Create a dependency analyzer instance
|
|
570
|
+
*/
|
|
571
|
+
export function createDependencyAnalyzer(): IDependencyAnalyzer {
|
|
572
|
+
return new DependencyAnalyzer()
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
/**
|
|
576
|
+
* Create a dependency node
|
|
577
|
+
*/
|
|
578
|
+
export function createDependencyNode(
|
|
579
|
+
id: string,
|
|
580
|
+
circuitId: string,
|
|
581
|
+
system: DependencyNode['system'],
|
|
582
|
+
options: {
|
|
583
|
+
dependencies?: string[]
|
|
584
|
+
estimatedCost?: number
|
|
585
|
+
estimatedMemory?: number
|
|
586
|
+
privateInputs?: Record<string, unknown>
|
|
587
|
+
publicInputs?: Record<string, unknown>
|
|
588
|
+
priority?: number
|
|
589
|
+
} = {}
|
|
590
|
+
): DependencyNode {
|
|
591
|
+
return {
|
|
592
|
+
id,
|
|
593
|
+
circuitId,
|
|
594
|
+
system,
|
|
595
|
+
dependencies: options.dependencies ?? [],
|
|
596
|
+
estimatedCost: options.estimatedCost ?? 100,
|
|
597
|
+
estimatedMemory: options.estimatedMemory ?? 64 * 1024 * 1024, // 64MB default
|
|
598
|
+
privateInputs: options.privateInputs ?? {},
|
|
599
|
+
publicInputs: options.publicInputs ?? {},
|
|
600
|
+
priority: options.priority,
|
|
601
|
+
}
|
|
602
|
+
}
|