@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,872 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compliance Proof Module
|
|
3
|
+
*
|
|
4
|
+
* USER-SIDE tool for generating ZK proofs for regulatory compliance.
|
|
5
|
+
*
|
|
6
|
+
* ## IMPORTANT: Protocol Neutrality
|
|
7
|
+
*
|
|
8
|
+
* **This module is for USERS to prove compliance — NOT protocol-level enforcement.**
|
|
9
|
+
*
|
|
10
|
+
* SIP Protocol follows the Zcash model:
|
|
11
|
+
* - Protocol is neutral infrastructure (like TCP/IP)
|
|
12
|
+
* - Protocol does NOT screen, block, or filter transactions
|
|
13
|
+
* - Users CHOOSE to generate compliance proofs when they need them
|
|
14
|
+
* - Compliance is voluntary, not mandatory
|
|
15
|
+
*
|
|
16
|
+
* This is why Zcash avoided OFAC sanctions while Tornado Cash was sanctioned:
|
|
17
|
+
* Zcash provides compliance TOOLS (viewing keys), not enforcement.
|
|
18
|
+
*
|
|
19
|
+
* ## Use Cases
|
|
20
|
+
*
|
|
21
|
+
* 1. **Viewing Key Disclosure**: User proves to auditor they can decrypt a transaction
|
|
22
|
+
* without revealing the transaction details
|
|
23
|
+
*
|
|
24
|
+
* 2. **Sanctions Self-Check**: User proves they checked sanctions list (their choice)
|
|
25
|
+
* — NOT protocol blocking sanctioned addresses
|
|
26
|
+
*
|
|
27
|
+
* 3. **Balance Attestation**: User proves sufficient funds without revealing balance
|
|
28
|
+
*
|
|
29
|
+
* 4. **Tax Compliance**: User proves transaction history is complete for tax filing
|
|
30
|
+
*
|
|
31
|
+
* ## Architecture
|
|
32
|
+
*
|
|
33
|
+
* ```
|
|
34
|
+
* ┌─────────────────────────────────────────────────────────────┐
|
|
35
|
+
* │ USER-SIDE COMPLIANCE PROOFS │
|
|
36
|
+
* │ (Protocol remains neutral — user generates proofs by choice)
|
|
37
|
+
* │ │
|
|
38
|
+
* │ ┌─────────────────┐ ┌─────────────────┐ │
|
|
39
|
+
* │ │ User │ │ Auditor/ │ │
|
|
40
|
+
* │ │ (generates │───►│ Regulator │ │
|
|
41
|
+
* │ │ proof) │ │ (verifies) │ │
|
|
42
|
+
* │ └─────────────────┘ └─────────────────┘ │
|
|
43
|
+
* │ │
|
|
44
|
+
* │ What user can prove: │
|
|
45
|
+
* │ ✓ Transaction exists and is valid │
|
|
46
|
+
* │ ✓ User has viewing key access │
|
|
47
|
+
* │ ✓ User checked sanctions list (voluntary) │
|
|
48
|
+
* │ │
|
|
49
|
+
* │ What remains hidden: │
|
|
50
|
+
* │ ✗ Actual transaction amount │
|
|
51
|
+
* │ ✗ Sender/recipient identities (unless user discloses) │
|
|
52
|
+
* │ ✗ Transaction path │
|
|
53
|
+
* └─────────────────────────────────────────────────────────────┘
|
|
54
|
+
* ```
|
|
55
|
+
*
|
|
56
|
+
* @module proofs/compliance-proof
|
|
57
|
+
*/
|
|
58
|
+
|
|
59
|
+
import type { ZKProof, ViewingKey } from '@sip-protocol/types'
|
|
60
|
+
import type { ProofResult } from './interface'
|
|
61
|
+
import { ProofGenerationError } from './interface'
|
|
62
|
+
import { ProofError, ErrorCode } from '../errors'
|
|
63
|
+
|
|
64
|
+
// ─── Types ───────────────────────────────────────────────────────────────────
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Compliance proof types
|
|
68
|
+
*/
|
|
69
|
+
export type ComplianceProofType =
|
|
70
|
+
| 'viewing_key_access' // Prove viewing key holder can access transaction
|
|
71
|
+
| 'sanctions_clear' // Prove no sanctions list matches
|
|
72
|
+
| 'balance_attestation' // Prove balance meets requirement
|
|
73
|
+
| 'history_complete' // Prove complete transaction history
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Parameters for viewing key access proof
|
|
77
|
+
*
|
|
78
|
+
* Proves that the holder of a viewing key can decrypt a specific transaction
|
|
79
|
+
* without revealing the decrypted contents.
|
|
80
|
+
*/
|
|
81
|
+
export interface ViewingKeyAccessParams {
|
|
82
|
+
/** The viewing key (private) */
|
|
83
|
+
viewingKey: ViewingKey
|
|
84
|
+
/** Transaction hash to prove access to */
|
|
85
|
+
transactionHash: string
|
|
86
|
+
/** Encrypted transaction data */
|
|
87
|
+
encryptedData: Uint8Array
|
|
88
|
+
/** Auditor's public key for verification */
|
|
89
|
+
auditorPublicKey: string
|
|
90
|
+
/** Timestamp of proof generation */
|
|
91
|
+
timestamp: number
|
|
92
|
+
/** Optional: Chain ID for multi-chain support */
|
|
93
|
+
chainId?: string
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Parameters for sanctions clearance proof
|
|
98
|
+
*
|
|
99
|
+
* Proves that sender and recipient are not on a sanctions list
|
|
100
|
+
* without revealing their actual addresses.
|
|
101
|
+
*/
|
|
102
|
+
export interface SanctionsClearParams {
|
|
103
|
+
/** Sender address (private) */
|
|
104
|
+
senderAddress: string
|
|
105
|
+
/** Recipient address (private) */
|
|
106
|
+
recipientAddress: string
|
|
107
|
+
/** Blinding factor for sender (private) */
|
|
108
|
+
senderBlinding: Uint8Array
|
|
109
|
+
/** Blinding factor for recipient (private) */
|
|
110
|
+
recipientBlinding: Uint8Array
|
|
111
|
+
/** Merkle root of known sanctions list (public) */
|
|
112
|
+
sanctionsListRoot: string
|
|
113
|
+
/** Timestamp of check */
|
|
114
|
+
checkTimestamp: number
|
|
115
|
+
/** Jurisdiction (e.g., "US", "EU") */
|
|
116
|
+
jurisdiction: string
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Parameters for balance attestation proof
|
|
121
|
+
*
|
|
122
|
+
* Proves balance meets a threshold without revealing exact balance.
|
|
123
|
+
*/
|
|
124
|
+
export interface BalanceAttestationParams {
|
|
125
|
+
/** Actual balance (private) */
|
|
126
|
+
balance: bigint
|
|
127
|
+
/** Blinding factor (private) */
|
|
128
|
+
blindingFactor: Uint8Array
|
|
129
|
+
/** Minimum required balance (public) */
|
|
130
|
+
minimumRequired: bigint
|
|
131
|
+
/** Asset identifier (public) */
|
|
132
|
+
assetId: string
|
|
133
|
+
/** Account identifier (public commitment) */
|
|
134
|
+
accountCommitment: string
|
|
135
|
+
/** Attestation timestamp */
|
|
136
|
+
attestationTime: number
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Parameters for history completeness proof
|
|
141
|
+
*
|
|
142
|
+
* Proves that all transactions in a time range have been disclosed
|
|
143
|
+
* without revealing transaction amounts.
|
|
144
|
+
*/
|
|
145
|
+
export interface HistoryCompletenessParams {
|
|
146
|
+
/** Transaction count in range (private) */
|
|
147
|
+
transactionCount: number
|
|
148
|
+
/** Merkle root of transaction hashes (public) */
|
|
149
|
+
historyMerkleRoot: string
|
|
150
|
+
/** Start of time range (public) */
|
|
151
|
+
startTimestamp: number
|
|
152
|
+
/** End of time range (public) */
|
|
153
|
+
endTimestamp: number
|
|
154
|
+
/** Total volume commitment (public) */
|
|
155
|
+
volumeCommitment: string
|
|
156
|
+
/** Viewing key for verification */
|
|
157
|
+
viewingKey: ViewingKey
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Compliance proof result
|
|
162
|
+
*/
|
|
163
|
+
export interface ComplianceProofResult extends ProofResult {
|
|
164
|
+
/** Type of compliance proof */
|
|
165
|
+
complianceType: ComplianceProofType
|
|
166
|
+
/** Expiry time for this proof (Unix timestamp) */
|
|
167
|
+
validUntil: number
|
|
168
|
+
/** Jurisdiction this proof is valid for */
|
|
169
|
+
jurisdiction?: string
|
|
170
|
+
/** Auditor verification hash */
|
|
171
|
+
auditorHash?: string
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Compliance proof provider configuration
|
|
176
|
+
*/
|
|
177
|
+
export interface ComplianceProofConfig {
|
|
178
|
+
/** Default proof validity period in seconds */
|
|
179
|
+
defaultValidityPeriod?: number
|
|
180
|
+
/** Enable verbose logging */
|
|
181
|
+
verbose?: boolean
|
|
182
|
+
/** Supported jurisdictions */
|
|
183
|
+
jurisdictions?: string[]
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// ─── Constants ───────────────────────────────────────────────────────────────
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Default proof validity period (24 hours)
|
|
190
|
+
*/
|
|
191
|
+
export const DEFAULT_VALIDITY_PERIOD_SECONDS = 86400
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Supported compliance jurisdictions
|
|
195
|
+
*/
|
|
196
|
+
export const SUPPORTED_JURISDICTIONS = [
|
|
197
|
+
'US', // United States
|
|
198
|
+
'EU', // European Union
|
|
199
|
+
'UK', // United Kingdom
|
|
200
|
+
'SG', // Singapore
|
|
201
|
+
'CH', // Switzerland
|
|
202
|
+
'GLOBAL', // Global sanctions lists
|
|
203
|
+
] as const
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Compliance proof circuit IDs
|
|
207
|
+
*/
|
|
208
|
+
export const COMPLIANCE_CIRCUIT_IDS = {
|
|
209
|
+
viewing_key_access: 'compliance_viewing_key_v1',
|
|
210
|
+
sanctions_clear: 'compliance_sanctions_v1',
|
|
211
|
+
balance_attestation: 'compliance_balance_v1',
|
|
212
|
+
history_complete: 'compliance_history_v1',
|
|
213
|
+
} as const
|
|
214
|
+
|
|
215
|
+
// ─── Provider ────────────────────────────────────────────────────────────────
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Compliance Proof Provider
|
|
219
|
+
*
|
|
220
|
+
* Generates ZK proofs for regulatory compliance without revealing sensitive data.
|
|
221
|
+
*
|
|
222
|
+
* @example
|
|
223
|
+
* ```typescript
|
|
224
|
+
* const provider = new ComplianceProofProvider()
|
|
225
|
+
* await provider.initialize()
|
|
226
|
+
*
|
|
227
|
+
* // Prove viewing key access to auditor
|
|
228
|
+
* const result = await provider.generateViewingKeyAccessProof({
|
|
229
|
+
* viewingKey: myViewingKey,
|
|
230
|
+
* transactionHash: '0x...',
|
|
231
|
+
* encryptedData: encryptedTxData,
|
|
232
|
+
* auditorPublicKey: '0x...',
|
|
233
|
+
* timestamp: Date.now(),
|
|
234
|
+
* })
|
|
235
|
+
*
|
|
236
|
+
* // Share proof with auditor (they can verify without seeing data)
|
|
237
|
+
* await sendToAuditor(result.proof)
|
|
238
|
+
* ```
|
|
239
|
+
*/
|
|
240
|
+
export class ComplianceProofProvider {
|
|
241
|
+
private config: Required<ComplianceProofConfig>
|
|
242
|
+
private _isReady = false
|
|
243
|
+
|
|
244
|
+
constructor(config: ComplianceProofConfig = {}) {
|
|
245
|
+
this.config = {
|
|
246
|
+
defaultValidityPeriod: config.defaultValidityPeriod ?? DEFAULT_VALIDITY_PERIOD_SECONDS,
|
|
247
|
+
verbose: config.verbose ?? false,
|
|
248
|
+
jurisdictions: config.jurisdictions ?? [...SUPPORTED_JURISDICTIONS],
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Check if provider is initialized
|
|
254
|
+
*/
|
|
255
|
+
get isReady(): boolean {
|
|
256
|
+
return this._isReady
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Initialize the compliance proof provider
|
|
261
|
+
*/
|
|
262
|
+
async initialize(): Promise<void> {
|
|
263
|
+
if (this._isReady) {
|
|
264
|
+
return
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
if (this.config.verbose) {
|
|
268
|
+
console.log('[ComplianceProofProvider] Initializing...')
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// In production, this would load compliance-specific circuits
|
|
272
|
+
// For now, we reuse the existing Noir circuits with compliance parameters
|
|
273
|
+
|
|
274
|
+
this._isReady = true
|
|
275
|
+
|
|
276
|
+
if (this.config.verbose) {
|
|
277
|
+
console.log('[ComplianceProofProvider] Ready')
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Generate a viewing key access proof
|
|
283
|
+
*
|
|
284
|
+
* Proves to an auditor that the holder of a viewing key can decrypt
|
|
285
|
+
* a specific transaction without revealing the decrypted contents.
|
|
286
|
+
*
|
|
287
|
+
* @param params - Viewing key access parameters
|
|
288
|
+
* @returns Compliance proof result
|
|
289
|
+
*/
|
|
290
|
+
async generateViewingKeyAccessProof(
|
|
291
|
+
params: ViewingKeyAccessParams
|
|
292
|
+
): Promise<ComplianceProofResult> {
|
|
293
|
+
this.ensureReady()
|
|
294
|
+
|
|
295
|
+
if (this.config.verbose) {
|
|
296
|
+
console.log('[ComplianceProofProvider] Generating viewing key access proof...')
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
try {
|
|
300
|
+
// Validate parameters
|
|
301
|
+
this.validateViewingKeyAccessParams(params)
|
|
302
|
+
|
|
303
|
+
// Compute proof components
|
|
304
|
+
const viewingKeyHash = await this.hashViewingKey(params.viewingKey)
|
|
305
|
+
const decryptionCommitment = await this.computeDecryptionCommitment(
|
|
306
|
+
params.viewingKey,
|
|
307
|
+
params.encryptedData
|
|
308
|
+
)
|
|
309
|
+
const auditorHash = await this.computeAuditorHash(
|
|
310
|
+
params.auditorPublicKey,
|
|
311
|
+
params.transactionHash
|
|
312
|
+
)
|
|
313
|
+
|
|
314
|
+
// Build public inputs
|
|
315
|
+
const publicInputs: `0x${string}`[] = [
|
|
316
|
+
`0x${params.transactionHash.replace('0x', '').padStart(64, '0')}`,
|
|
317
|
+
`0x${viewingKeyHash}`,
|
|
318
|
+
`0x${decryptionCommitment}`,
|
|
319
|
+
`0x${params.timestamp.toString(16).padStart(16, '0')}`,
|
|
320
|
+
`0x${auditorHash}`,
|
|
321
|
+
]
|
|
322
|
+
|
|
323
|
+
// Generate proof (in production, this would use the Noir circuit)
|
|
324
|
+
const proofBytes = await this.generateComplianceProofBytes(
|
|
325
|
+
'viewing_key_access',
|
|
326
|
+
publicInputs
|
|
327
|
+
)
|
|
328
|
+
|
|
329
|
+
const proof: ZKProof = {
|
|
330
|
+
type: 'validity', // Reuses validity proof structure
|
|
331
|
+
proof: `0x${proofBytes}`,
|
|
332
|
+
publicInputs,
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
const validUntil = params.timestamp + this.config.defaultValidityPeriod
|
|
336
|
+
|
|
337
|
+
if (this.config.verbose) {
|
|
338
|
+
console.log('[ComplianceProofProvider] Viewing key access proof generated')
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
return {
|
|
342
|
+
proof,
|
|
343
|
+
publicInputs,
|
|
344
|
+
complianceType: 'viewing_key_access',
|
|
345
|
+
validUntil,
|
|
346
|
+
auditorHash,
|
|
347
|
+
}
|
|
348
|
+
} catch (error) {
|
|
349
|
+
throw new ProofGenerationError(
|
|
350
|
+
'validity', // Viewing key access uses validity proof structure
|
|
351
|
+
`Failed to generate viewing key access proof: ${error instanceof Error ? error.message : String(error)}`,
|
|
352
|
+
error instanceof Error ? error : undefined
|
|
353
|
+
)
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Generate a sanctions clearance proof
|
|
359
|
+
*
|
|
360
|
+
* Proves that sender and recipient are not on any sanctions lists
|
|
361
|
+
* without revealing their actual addresses.
|
|
362
|
+
*
|
|
363
|
+
* @param params - Sanctions clearance parameters
|
|
364
|
+
* @returns Compliance proof result
|
|
365
|
+
*/
|
|
366
|
+
async generateSanctionsClearProof(
|
|
367
|
+
params: SanctionsClearParams
|
|
368
|
+
): Promise<ComplianceProofResult> {
|
|
369
|
+
this.ensureReady()
|
|
370
|
+
|
|
371
|
+
if (this.config.verbose) {
|
|
372
|
+
console.log('[ComplianceProofProvider] Generating sanctions clearance proof...')
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
try {
|
|
376
|
+
// Validate parameters
|
|
377
|
+
this.validateSanctionsClearParams(params)
|
|
378
|
+
|
|
379
|
+
// Compute address commitments (hide actual addresses)
|
|
380
|
+
const senderCommitment = await this.computeAddressCommitment(
|
|
381
|
+
params.senderAddress,
|
|
382
|
+
params.senderBlinding
|
|
383
|
+
)
|
|
384
|
+
const recipientCommitment = await this.computeAddressCommitment(
|
|
385
|
+
params.recipientAddress,
|
|
386
|
+
params.recipientBlinding
|
|
387
|
+
)
|
|
388
|
+
|
|
389
|
+
// Compute non-membership proof in sanctions list
|
|
390
|
+
const nonMembershipProof = await this.computeNonMembershipProof(
|
|
391
|
+
params.senderAddress,
|
|
392
|
+
params.recipientAddress,
|
|
393
|
+
params.sanctionsListRoot
|
|
394
|
+
)
|
|
395
|
+
|
|
396
|
+
// Build public inputs
|
|
397
|
+
const publicInputs: `0x${string}`[] = [
|
|
398
|
+
`0x${senderCommitment}`,
|
|
399
|
+
`0x${recipientCommitment}`,
|
|
400
|
+
`0x${params.sanctionsListRoot.replace('0x', '').padStart(64, '0')}`,
|
|
401
|
+
`0x${params.checkTimestamp.toString(16).padStart(16, '0')}`,
|
|
402
|
+
`0x${nonMembershipProof}`,
|
|
403
|
+
]
|
|
404
|
+
|
|
405
|
+
// Generate proof
|
|
406
|
+
const proofBytes = await this.generateComplianceProofBytes(
|
|
407
|
+
'sanctions_clear',
|
|
408
|
+
publicInputs
|
|
409
|
+
)
|
|
410
|
+
|
|
411
|
+
const proof: ZKProof = {
|
|
412
|
+
type: 'validity',
|
|
413
|
+
proof: `0x${proofBytes}`,
|
|
414
|
+
publicInputs,
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
const validUntil = params.checkTimestamp + this.config.defaultValidityPeriod
|
|
418
|
+
|
|
419
|
+
if (this.config.verbose) {
|
|
420
|
+
console.log('[ComplianceProofProvider] Sanctions clearance proof generated')
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
return {
|
|
424
|
+
proof,
|
|
425
|
+
publicInputs,
|
|
426
|
+
complianceType: 'sanctions_clear',
|
|
427
|
+
validUntil,
|
|
428
|
+
jurisdiction: params.jurisdiction,
|
|
429
|
+
}
|
|
430
|
+
} catch (error) {
|
|
431
|
+
throw new ProofGenerationError(
|
|
432
|
+
'validity', // Sanctions clearance uses validity proof structure
|
|
433
|
+
`Failed to generate sanctions clearance proof: ${error instanceof Error ? error.message : String(error)}`,
|
|
434
|
+
error instanceof Error ? error : undefined
|
|
435
|
+
)
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* Generate a balance attestation proof
|
|
441
|
+
*
|
|
442
|
+
* Proves that an account has at least a certain balance
|
|
443
|
+
* without revealing the exact balance.
|
|
444
|
+
*
|
|
445
|
+
* @param params - Balance attestation parameters
|
|
446
|
+
* @returns Compliance proof result
|
|
447
|
+
*/
|
|
448
|
+
async generateBalanceAttestationProof(
|
|
449
|
+
params: BalanceAttestationParams
|
|
450
|
+
): Promise<ComplianceProofResult> {
|
|
451
|
+
this.ensureReady()
|
|
452
|
+
|
|
453
|
+
if (this.config.verbose) {
|
|
454
|
+
console.log('[ComplianceProofProvider] Generating balance attestation proof...')
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
try {
|
|
458
|
+
// Validate parameters
|
|
459
|
+
this.validateBalanceAttestationParams(params)
|
|
460
|
+
|
|
461
|
+
// Compute balance commitment
|
|
462
|
+
const balanceCommitment = await this.computeBalanceCommitment(
|
|
463
|
+
params.balance,
|
|
464
|
+
params.blindingFactor
|
|
465
|
+
)
|
|
466
|
+
|
|
467
|
+
// Build public inputs
|
|
468
|
+
const publicInputs: `0x${string}`[] = [
|
|
469
|
+
`0x${params.minimumRequired.toString(16).padStart(64, '0')}`,
|
|
470
|
+
`0x${params.assetId.replace('0x', '').padStart(64, '0')}`,
|
|
471
|
+
`0x${params.accountCommitment.replace('0x', '').padStart(64, '0')}`,
|
|
472
|
+
`0x${balanceCommitment}`,
|
|
473
|
+
`0x${params.attestationTime.toString(16).padStart(16, '0')}`,
|
|
474
|
+
]
|
|
475
|
+
|
|
476
|
+
// Generate proof (reuses funding proof logic)
|
|
477
|
+
const proofBytes = await this.generateComplianceProofBytes(
|
|
478
|
+
'balance_attestation',
|
|
479
|
+
publicInputs
|
|
480
|
+
)
|
|
481
|
+
|
|
482
|
+
const proof: ZKProof = {
|
|
483
|
+
type: 'funding', // Reuses funding proof structure
|
|
484
|
+
proof: `0x${proofBytes}`,
|
|
485
|
+
publicInputs,
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
const validUntil = params.attestationTime + this.config.defaultValidityPeriod
|
|
489
|
+
|
|
490
|
+
if (this.config.verbose) {
|
|
491
|
+
console.log('[ComplianceProofProvider] Balance attestation proof generated')
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
return {
|
|
495
|
+
proof,
|
|
496
|
+
publicInputs,
|
|
497
|
+
complianceType: 'balance_attestation',
|
|
498
|
+
validUntil,
|
|
499
|
+
}
|
|
500
|
+
} catch (error) {
|
|
501
|
+
throw new ProofGenerationError(
|
|
502
|
+
'funding', // Balance attestation uses funding proof structure
|
|
503
|
+
`Failed to generate balance attestation proof: ${error instanceof Error ? error.message : String(error)}`,
|
|
504
|
+
error instanceof Error ? error : undefined
|
|
505
|
+
)
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
/**
|
|
510
|
+
* Generate a history completeness proof
|
|
511
|
+
*
|
|
512
|
+
* Proves that all transactions in a time range have been disclosed
|
|
513
|
+
* without revealing individual transaction amounts.
|
|
514
|
+
*
|
|
515
|
+
* @param params - History completeness parameters
|
|
516
|
+
* @returns Compliance proof result
|
|
517
|
+
*/
|
|
518
|
+
async generateHistoryCompletenessProof(
|
|
519
|
+
params: HistoryCompletenessParams
|
|
520
|
+
): Promise<ComplianceProofResult> {
|
|
521
|
+
this.ensureReady()
|
|
522
|
+
|
|
523
|
+
if (this.config.verbose) {
|
|
524
|
+
console.log('[ComplianceProofProvider] Generating history completeness proof...')
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
try {
|
|
528
|
+
// Validate parameters
|
|
529
|
+
this.validateHistoryCompletenessParams(params)
|
|
530
|
+
|
|
531
|
+
// Compute viewing key hash
|
|
532
|
+
const viewingKeyHash = await this.hashViewingKey(params.viewingKey)
|
|
533
|
+
|
|
534
|
+
// Build public inputs
|
|
535
|
+
const publicInputs: `0x${string}`[] = [
|
|
536
|
+
`0x${params.historyMerkleRoot.replace('0x', '').padStart(64, '0')}`,
|
|
537
|
+
`0x${params.startTimestamp.toString(16).padStart(16, '0')}`,
|
|
538
|
+
`0x${params.endTimestamp.toString(16).padStart(16, '0')}`,
|
|
539
|
+
`0x${params.volumeCommitment.replace('0x', '').padStart(64, '0')}`,
|
|
540
|
+
`0x${viewingKeyHash}`,
|
|
541
|
+
]
|
|
542
|
+
|
|
543
|
+
// Generate proof
|
|
544
|
+
const proofBytes = await this.generateComplianceProofBytes(
|
|
545
|
+
'history_complete',
|
|
546
|
+
publicInputs
|
|
547
|
+
)
|
|
548
|
+
|
|
549
|
+
const proof: ZKProof = {
|
|
550
|
+
type: 'fulfillment', // Reuses fulfillment proof structure
|
|
551
|
+
proof: `0x${proofBytes}`,
|
|
552
|
+
publicInputs,
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
const validUntil = params.endTimestamp + this.config.defaultValidityPeriod
|
|
556
|
+
|
|
557
|
+
if (this.config.verbose) {
|
|
558
|
+
console.log('[ComplianceProofProvider] History completeness proof generated')
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
return {
|
|
562
|
+
proof,
|
|
563
|
+
publicInputs,
|
|
564
|
+
complianceType: 'history_complete',
|
|
565
|
+
validUntil,
|
|
566
|
+
}
|
|
567
|
+
} catch (error) {
|
|
568
|
+
throw new ProofGenerationError(
|
|
569
|
+
'fulfillment', // History completeness uses fulfillment proof structure
|
|
570
|
+
`Failed to generate history completeness proof: ${error instanceof Error ? error.message : String(error)}`,
|
|
571
|
+
error instanceof Error ? error : undefined
|
|
572
|
+
)
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
/**
|
|
577
|
+
* Verify a compliance proof
|
|
578
|
+
*
|
|
579
|
+
* @param result - Compliance proof result to verify
|
|
580
|
+
* @returns true if valid, false otherwise
|
|
581
|
+
*
|
|
582
|
+
* @remarks
|
|
583
|
+
* **IMPORTANT: Mock Implementation**
|
|
584
|
+
*
|
|
585
|
+
* This verification performs structural validation only:
|
|
586
|
+
* - Checks proof expiry
|
|
587
|
+
* - Validates proof format and size
|
|
588
|
+
* - Verifies public inputs exist
|
|
589
|
+
* - Checks proof type matches compliance type
|
|
590
|
+
*
|
|
591
|
+
* It does NOT perform cryptographic verification of the ZK proof.
|
|
592
|
+
* For production use, integrate with `SolanaNoirVerifier.verifyOffChain()`
|
|
593
|
+
* or deploy a dedicated compliance circuit verifier.
|
|
594
|
+
*
|
|
595
|
+
* @example
|
|
596
|
+
* ```typescript
|
|
597
|
+
* // For production cryptographic verification:
|
|
598
|
+
* const solanaVerifier = new SolanaNoirVerifier()
|
|
599
|
+
* await solanaVerifier.initialize()
|
|
600
|
+
* const cryptoValid = await solanaVerifier.verifyOffChain(result.proof)
|
|
601
|
+
* const formatValid = await complianceProvider.verifyComplianceProof(result)
|
|
602
|
+
* const isValid = cryptoValid && formatValid
|
|
603
|
+
* ```
|
|
604
|
+
*/
|
|
605
|
+
async verifyComplianceProof(result: ComplianceProofResult): Promise<boolean> {
|
|
606
|
+
this.ensureReady()
|
|
607
|
+
|
|
608
|
+
// Check if proof has expired
|
|
609
|
+
if (Date.now() / 1000 > result.validUntil) {
|
|
610
|
+
if (this.config.verbose) {
|
|
611
|
+
console.log('[ComplianceProofProvider] Proof has expired')
|
|
612
|
+
}
|
|
613
|
+
return false
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
// NOTE: This is a mock verification that only checks structure.
|
|
617
|
+
// Production systems should use SolanaNoirVerifier for cryptographic verification.
|
|
618
|
+
|
|
619
|
+
// Verify the underlying ZK proof structure
|
|
620
|
+
const proofHex = result.proof.proof.replace('0x', '')
|
|
621
|
+
|
|
622
|
+
// Check proof has minimum expected size (real proofs are ~2KB)
|
|
623
|
+
if (proofHex.length < 64) {
|
|
624
|
+
if (this.config.verbose) {
|
|
625
|
+
console.log('[ComplianceProofProvider] Proof too small')
|
|
626
|
+
}
|
|
627
|
+
return false
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
// Check public inputs match expected format
|
|
631
|
+
if (result.publicInputs.length === 0) {
|
|
632
|
+
if (this.config.verbose) {
|
|
633
|
+
console.log('[ComplianceProofProvider] No public inputs')
|
|
634
|
+
}
|
|
635
|
+
return false
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
// Check proof type matches compliance type
|
|
639
|
+
const expectedType = this.getExpectedProofType(result.complianceType)
|
|
640
|
+
if (result.proof.type !== expectedType) {
|
|
641
|
+
if (this.config.verbose) {
|
|
642
|
+
console.log(`[ComplianceProofProvider] Type mismatch: expected ${expectedType}, got ${result.proof.type}`)
|
|
643
|
+
}
|
|
644
|
+
return false
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
if (this.config.verbose) {
|
|
648
|
+
console.log('[ComplianceProofProvider] Mock verification: VALID (structural only, not cryptographic)')
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
return true
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
/**
|
|
655
|
+
* Destroy the provider and free resources
|
|
656
|
+
*/
|
|
657
|
+
async destroy(): Promise<void> {
|
|
658
|
+
this._isReady = false
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
// ─── Private Methods ───────────────────────────────────────────────────────
|
|
662
|
+
|
|
663
|
+
private ensureReady(): void {
|
|
664
|
+
if (!this._isReady) {
|
|
665
|
+
throw new ProofError(
|
|
666
|
+
'ComplianceProofProvider not initialized. Call initialize() first.',
|
|
667
|
+
ErrorCode.PROOF_PROVIDER_NOT_READY
|
|
668
|
+
)
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
private validateViewingKeyAccessParams(params: ViewingKeyAccessParams): void {
|
|
673
|
+
if (!params.viewingKey) {
|
|
674
|
+
throw new ProofError('Viewing key is required', ErrorCode.VALIDATION_FAILED)
|
|
675
|
+
}
|
|
676
|
+
if (!params.transactionHash) {
|
|
677
|
+
throw new ProofError('Transaction hash is required', ErrorCode.VALIDATION_FAILED)
|
|
678
|
+
}
|
|
679
|
+
if (!params.encryptedData || params.encryptedData.length === 0) {
|
|
680
|
+
throw new ProofError('Encrypted data is required', ErrorCode.VALIDATION_FAILED)
|
|
681
|
+
}
|
|
682
|
+
if (!params.auditorPublicKey) {
|
|
683
|
+
throw new ProofError('Auditor public key is required', ErrorCode.VALIDATION_FAILED)
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
private validateSanctionsClearParams(params: SanctionsClearParams): void {
|
|
688
|
+
if (!params.senderAddress) {
|
|
689
|
+
throw new ProofError('Sender address is required', ErrorCode.VALIDATION_FAILED)
|
|
690
|
+
}
|
|
691
|
+
if (!params.recipientAddress) {
|
|
692
|
+
throw new ProofError('Recipient address is required', ErrorCode.VALIDATION_FAILED)
|
|
693
|
+
}
|
|
694
|
+
if (!params.sanctionsListRoot) {
|
|
695
|
+
throw new ProofError('Sanctions list root is required', ErrorCode.VALIDATION_FAILED)
|
|
696
|
+
}
|
|
697
|
+
if (!this.config.jurisdictions.includes(params.jurisdiction as never)) {
|
|
698
|
+
throw new ProofError(
|
|
699
|
+
`Unsupported jurisdiction: ${params.jurisdiction}`,
|
|
700
|
+
ErrorCode.VALIDATION_FAILED
|
|
701
|
+
)
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
private validateBalanceAttestationParams(params: BalanceAttestationParams): void {
|
|
706
|
+
if (params.balance < 0n) {
|
|
707
|
+
throw new ProofError('Balance cannot be negative', ErrorCode.VALIDATION_FAILED)
|
|
708
|
+
}
|
|
709
|
+
if (params.balance < params.minimumRequired) {
|
|
710
|
+
throw new ProofError(
|
|
711
|
+
'Balance must be at least minimum required',
|
|
712
|
+
ErrorCode.VALIDATION_FAILED
|
|
713
|
+
)
|
|
714
|
+
}
|
|
715
|
+
if (!params.assetId) {
|
|
716
|
+
throw new ProofError('Asset ID is required', ErrorCode.VALIDATION_FAILED)
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
private validateHistoryCompletenessParams(params: HistoryCompletenessParams): void {
|
|
721
|
+
if (params.startTimestamp >= params.endTimestamp) {
|
|
722
|
+
throw new ProofError('Start must be before end', ErrorCode.VALIDATION_FAILED)
|
|
723
|
+
}
|
|
724
|
+
if (!params.historyMerkleRoot) {
|
|
725
|
+
throw new ProofError('History merkle root is required', ErrorCode.VALIDATION_FAILED)
|
|
726
|
+
}
|
|
727
|
+
if (!params.viewingKey) {
|
|
728
|
+
throw new ProofError('Viewing key is required', ErrorCode.VALIDATION_FAILED)
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
private async hashViewingKey(viewingKey: ViewingKey): Promise<string> {
|
|
733
|
+
const { sha256 } = await import('@noble/hashes/sha256')
|
|
734
|
+
const { bytesToHex } = await import('@noble/hashes/utils')
|
|
735
|
+
|
|
736
|
+
// Hash the viewing key public component
|
|
737
|
+
const keyString = typeof viewingKey === 'string' ? viewingKey : JSON.stringify(viewingKey)
|
|
738
|
+
const encoder = new TextEncoder()
|
|
739
|
+
const keyBytes = encoder.encode(keyString)
|
|
740
|
+
|
|
741
|
+
return bytesToHex(sha256(keyBytes))
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
private async computeDecryptionCommitment(
|
|
745
|
+
viewingKey: ViewingKey,
|
|
746
|
+
encryptedData: Uint8Array
|
|
747
|
+
): Promise<string> {
|
|
748
|
+
const { sha256 } = await import('@noble/hashes/sha256')
|
|
749
|
+
const { bytesToHex } = await import('@noble/hashes/utils')
|
|
750
|
+
|
|
751
|
+
// Commitment: hash(viewing_key || encrypted_data)
|
|
752
|
+
const keyHash = await this.hashViewingKey(viewingKey)
|
|
753
|
+
const keyBytes = this.hexToBytes(keyHash)
|
|
754
|
+
|
|
755
|
+
const preimage = new Uint8Array([...keyBytes, ...encryptedData.slice(0, 32)])
|
|
756
|
+
return bytesToHex(sha256(preimage))
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
private async computeAuditorHash(
|
|
760
|
+
auditorPublicKey: string,
|
|
761
|
+
transactionHash: string
|
|
762
|
+
): Promise<string> {
|
|
763
|
+
const { sha256 } = await import('@noble/hashes/sha256')
|
|
764
|
+
const { bytesToHex } = await import('@noble/hashes/utils')
|
|
765
|
+
|
|
766
|
+
const auditorBytes = this.hexToBytes(auditorPublicKey.replace('0x', '').padStart(64, '0'))
|
|
767
|
+
const txBytes = this.hexToBytes(transactionHash.replace('0x', '').padStart(64, '0'))
|
|
768
|
+
|
|
769
|
+
const preimage = new Uint8Array([...auditorBytes, ...txBytes])
|
|
770
|
+
return bytesToHex(sha256(preimage))
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
private async computeAddressCommitment(
|
|
774
|
+
address: string,
|
|
775
|
+
blinding: Uint8Array
|
|
776
|
+
): Promise<string> {
|
|
777
|
+
const { sha256 } = await import('@noble/hashes/sha256')
|
|
778
|
+
const { bytesToHex } = await import('@noble/hashes/utils')
|
|
779
|
+
|
|
780
|
+
const addressBytes = this.hexToBytes(address.replace('0x', '').padStart(64, '0'))
|
|
781
|
+
const preimage = new Uint8Array([...addressBytes, ...blinding.slice(0, 32)])
|
|
782
|
+
|
|
783
|
+
return bytesToHex(sha256(preimage))
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
private async computeNonMembershipProof(
|
|
787
|
+
senderAddress: string,
|
|
788
|
+
recipientAddress: string,
|
|
789
|
+
_sanctionsListRoot: string
|
|
790
|
+
): Promise<string> {
|
|
791
|
+
const { sha256 } = await import('@noble/hashes/sha256')
|
|
792
|
+
const { bytesToHex } = await import('@noble/hashes/utils')
|
|
793
|
+
|
|
794
|
+
// In production, this would be a Merkle non-membership proof
|
|
795
|
+
// For now, we generate a commitment that can be verified
|
|
796
|
+
const senderBytes = this.hexToBytes(senderAddress.replace('0x', '').padStart(64, '0'))
|
|
797
|
+
const recipientBytes = this.hexToBytes(recipientAddress.replace('0x', '').padStart(64, '0'))
|
|
798
|
+
|
|
799
|
+
const preimage = new Uint8Array([...senderBytes, ...recipientBytes])
|
|
800
|
+
return bytesToHex(sha256(preimage))
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
private async computeBalanceCommitment(
|
|
804
|
+
balance: bigint,
|
|
805
|
+
blinding: Uint8Array
|
|
806
|
+
): Promise<string> {
|
|
807
|
+
const { sha256 } = await import('@noble/hashes/sha256')
|
|
808
|
+
const { bytesToHex } = await import('@noble/hashes/utils')
|
|
809
|
+
|
|
810
|
+
// Convert balance to bytes
|
|
811
|
+
const balanceBytes = new Uint8Array(8)
|
|
812
|
+
let v = balance
|
|
813
|
+
for (let i = 7; i >= 0; i--) {
|
|
814
|
+
balanceBytes[i] = Number(v & 0xffn)
|
|
815
|
+
v = v >> 8n
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
const preimage = new Uint8Array([...balanceBytes, ...blinding.slice(0, 32)])
|
|
819
|
+
return bytesToHex(sha256(preimage))
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
private async generateComplianceProofBytes(
|
|
823
|
+
type: ComplianceProofType,
|
|
824
|
+
publicInputs: string[]
|
|
825
|
+
): Promise<string> {
|
|
826
|
+
const { sha256 } = await import('@noble/hashes/sha256')
|
|
827
|
+
const { bytesToHex } = await import('@noble/hashes/utils')
|
|
828
|
+
|
|
829
|
+
// In production, this would call the Noir circuit
|
|
830
|
+
// For mock, we generate deterministic proof bytes from inputs
|
|
831
|
+
const circuitId = COMPLIANCE_CIRCUIT_IDS[type]
|
|
832
|
+
const encoder = new TextEncoder()
|
|
833
|
+
|
|
834
|
+
const inputBytes = publicInputs.flatMap((pi) => Array.from(this.hexToBytes(pi.replace('0x', ''))))
|
|
835
|
+
const preimage = new Uint8Array([
|
|
836
|
+
...encoder.encode(circuitId),
|
|
837
|
+
...inputBytes,
|
|
838
|
+
])
|
|
839
|
+
|
|
840
|
+
// Generate 256 bytes of proof data (typical proof size)
|
|
841
|
+
const hash = sha256(preimage)
|
|
842
|
+
let proofBytes = ''
|
|
843
|
+
for (let i = 0; i < 8; i++) {
|
|
844
|
+
proofBytes += bytesToHex(sha256(new Uint8Array([...hash, i])))
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
return proofBytes
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
private getExpectedProofType(complianceType: ComplianceProofType): string {
|
|
851
|
+
switch (complianceType) {
|
|
852
|
+
case 'viewing_key_access':
|
|
853
|
+
case 'sanctions_clear':
|
|
854
|
+
return 'validity'
|
|
855
|
+
case 'balance_attestation':
|
|
856
|
+
return 'funding'
|
|
857
|
+
case 'history_complete':
|
|
858
|
+
return 'fulfillment'
|
|
859
|
+
default:
|
|
860
|
+
return 'validity'
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
private hexToBytes(hex: string): Uint8Array {
|
|
865
|
+
const h = hex.startsWith('0x') ? hex.slice(2) : hex
|
|
866
|
+
const bytes = new Uint8Array(h.length / 2)
|
|
867
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
868
|
+
bytes[i] = parseInt(h.slice(i * 2, i * 2 + 2), 16)
|
|
869
|
+
}
|
|
870
|
+
return bytes
|
|
871
|
+
}
|
|
872
|
+
}
|