@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,639 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Winternitz Vault Integration for Quantum-Resistant Storage
|
|
3
|
+
*
|
|
4
|
+
* Combines SIP's privacy layer (stealth addresses, Pedersen commitments,
|
|
5
|
+
* viewing keys) with Winternitz vaults for post-quantum security.
|
|
6
|
+
*
|
|
7
|
+
* ## Security Model
|
|
8
|
+
*
|
|
9
|
+
* ```
|
|
10
|
+
* Layer 3: COMPLIANCE (Viewing Keys)
|
|
11
|
+
* └── Selective disclosure to auditors
|
|
12
|
+
* Layer 2: PRIVACY (SIP)
|
|
13
|
+
* └── Hidden sender/amount/recipient
|
|
14
|
+
* Layer 1: QUANTUM RESISTANCE (Winternitz)
|
|
15
|
+
* └── 128-bit post-quantum security
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* ## Usage
|
|
19
|
+
*
|
|
20
|
+
* ```typescript
|
|
21
|
+
* import { WinternitzVaultAdapter } from '@sip-protocol/sdk/quantum'
|
|
22
|
+
*
|
|
23
|
+
* const adapter = new WinternitzVaultAdapter({
|
|
24
|
+
* connection: new Connection('https://api.mainnet-beta.solana.com'),
|
|
25
|
+
* })
|
|
26
|
+
*
|
|
27
|
+
* // Open quantum-safe vault
|
|
28
|
+
* const vault = await adapter.openVault({
|
|
29
|
+
* amount: 1_000_000_000n,
|
|
30
|
+
* recipient: recipientMetaAddress,
|
|
31
|
+
* viewingKey: auditorKey,
|
|
32
|
+
* })
|
|
33
|
+
*
|
|
34
|
+
* // Send from vault (creates new vaults)
|
|
35
|
+
* const { recipientVault, changeVault } = await adapter.send({
|
|
36
|
+
* fromVault: vault,
|
|
37
|
+
* toRecipient: bobMetaAddress,
|
|
38
|
+
* amount: 500_000_000n,
|
|
39
|
+
* })
|
|
40
|
+
* ```
|
|
41
|
+
*
|
|
42
|
+
* @module quantum/winternitz-vault
|
|
43
|
+
*/
|
|
44
|
+
|
|
45
|
+
import { PublicKey, Connection, Transaction } from '@solana/web3.js'
|
|
46
|
+
import { keccak_256 } from '@noble/hashes/sha3'
|
|
47
|
+
import type { HexString } from '@sip-protocol/types'
|
|
48
|
+
import {
|
|
49
|
+
generateWinternitzKeypair,
|
|
50
|
+
wotsSign,
|
|
51
|
+
wotsVerify,
|
|
52
|
+
WotsKeyManager,
|
|
53
|
+
type WinternitzKeypair,
|
|
54
|
+
type WotsSignature,
|
|
55
|
+
} from './wots'
|
|
56
|
+
|
|
57
|
+
// ─── Types ────────────────────────────────────────────────────────────────────
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Shielded vault combining privacy + quantum resistance
|
|
61
|
+
*/
|
|
62
|
+
export interface ShieldedVault {
|
|
63
|
+
// === Winternitz Layer ===
|
|
64
|
+
/** WOTS public key merkle root (32 bytes) */
|
|
65
|
+
wotsMerkleRoot: Uint8Array
|
|
66
|
+
/** Vault PDA on Solana */
|
|
67
|
+
vaultAddress: PublicKey
|
|
68
|
+
/** Balance in lamports */
|
|
69
|
+
balance: bigint
|
|
70
|
+
|
|
71
|
+
// === SIP Privacy Layer ===
|
|
72
|
+
/** One-time stealth address */
|
|
73
|
+
stealthAddress: {
|
|
74
|
+
address: HexString
|
|
75
|
+
ephemeralPublicKey: HexString
|
|
76
|
+
viewTag: number
|
|
77
|
+
}
|
|
78
|
+
/** Pedersen commitment hiding the balance */
|
|
79
|
+
balanceCommitment: {
|
|
80
|
+
value: HexString
|
|
81
|
+
blindingFactor: HexString
|
|
82
|
+
}
|
|
83
|
+
/** Encrypted metadata for viewing key holders */
|
|
84
|
+
encryptedMetadata?: {
|
|
85
|
+
ciphertext: HexString
|
|
86
|
+
nonce: HexString
|
|
87
|
+
viewingKeyHash: HexString
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// === Vault State ===
|
|
91
|
+
/** Vault status */
|
|
92
|
+
status: 'active' | 'spent'
|
|
93
|
+
/** Creation timestamp */
|
|
94
|
+
createdAt: number
|
|
95
|
+
/** Chain identifier */
|
|
96
|
+
chain: 'solana'
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Decrypted vault metadata (visible to viewing key holders)
|
|
101
|
+
*/
|
|
102
|
+
export interface ShieldedVaultMetadata {
|
|
103
|
+
/** Actual balance */
|
|
104
|
+
balance: bigint
|
|
105
|
+
/** Blinding factor for commitment verification */
|
|
106
|
+
blindingFactor: HexString
|
|
107
|
+
/** Original sender (if disclosed) */
|
|
108
|
+
sender?: HexString
|
|
109
|
+
/** Purpose/memo */
|
|
110
|
+
memo?: string
|
|
111
|
+
/** Timestamp */
|
|
112
|
+
timestamp: number
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Parameters for opening a vault
|
|
117
|
+
*/
|
|
118
|
+
export interface OpenVaultParams {
|
|
119
|
+
/** Amount in lamports */
|
|
120
|
+
amount: bigint
|
|
121
|
+
/** Recipient stealth meta-address */
|
|
122
|
+
recipientMetaAddress: {
|
|
123
|
+
spendingPublicKey: HexString
|
|
124
|
+
viewingPublicKey: HexString
|
|
125
|
+
}
|
|
126
|
+
/** Viewing key for compliance (optional) */
|
|
127
|
+
viewingKey?: HexString
|
|
128
|
+
/** Payer for transaction */
|
|
129
|
+
payer: PublicKey
|
|
130
|
+
/** Transaction signer */
|
|
131
|
+
signTransaction: <T extends Transaction>(tx: T) => Promise<T>
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Parameters for splitting a vault
|
|
136
|
+
*/
|
|
137
|
+
export interface SplitVaultParams {
|
|
138
|
+
/** Source vault */
|
|
139
|
+
vault: ShieldedVault
|
|
140
|
+
/** Amount to send */
|
|
141
|
+
splitAmount: bigint
|
|
142
|
+
/** Split recipient meta-address */
|
|
143
|
+
splitRecipient: {
|
|
144
|
+
spendingPublicKey: HexString
|
|
145
|
+
viewingPublicKey: HexString
|
|
146
|
+
}
|
|
147
|
+
/** Refund recipient meta-address (usually self) */
|
|
148
|
+
refundRecipient: {
|
|
149
|
+
spendingPublicKey: HexString
|
|
150
|
+
viewingPublicKey: HexString
|
|
151
|
+
}
|
|
152
|
+
/** WOTS private key for source vault */
|
|
153
|
+
wotsPrivateKey: Uint8Array
|
|
154
|
+
/** Viewing key */
|
|
155
|
+
viewingKey?: HexString
|
|
156
|
+
/** Payer for transaction */
|
|
157
|
+
payer: PublicKey
|
|
158
|
+
/** Transaction signer */
|
|
159
|
+
signTransaction: <T extends Transaction>(tx: T) => Promise<T>
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Parameters for closing a vault
|
|
164
|
+
*/
|
|
165
|
+
export interface CloseVaultParams {
|
|
166
|
+
/** Vault to close */
|
|
167
|
+
vault: ShieldedVault
|
|
168
|
+
/** Recipient meta-address */
|
|
169
|
+
recipient: {
|
|
170
|
+
spendingPublicKey: HexString
|
|
171
|
+
viewingPublicKey: HexString
|
|
172
|
+
}
|
|
173
|
+
/** WOTS private key */
|
|
174
|
+
wotsPrivateKey: Uint8Array
|
|
175
|
+
/** Viewing key */
|
|
176
|
+
viewingKey?: HexString
|
|
177
|
+
/** Payer */
|
|
178
|
+
payer: PublicKey
|
|
179
|
+
/** Transaction signer */
|
|
180
|
+
signTransaction: <T extends Transaction>(tx: T) => Promise<T>
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Vault scan parameters
|
|
185
|
+
*/
|
|
186
|
+
export interface ScanVaultsParams {
|
|
187
|
+
/** Spending private key */
|
|
188
|
+
spendingPrivateKey: HexString
|
|
189
|
+
/** Viewing private key */
|
|
190
|
+
viewingPrivateKey: HexString
|
|
191
|
+
/** Vaults to scan */
|
|
192
|
+
vaults: ShieldedVault[]
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Adapter configuration
|
|
197
|
+
*/
|
|
198
|
+
export interface WinternitzVaultConfig {
|
|
199
|
+
/** Solana connection */
|
|
200
|
+
connection: Connection
|
|
201
|
+
/** Winternitz program ID (if deployed) */
|
|
202
|
+
programId?: PublicKey
|
|
203
|
+
/** Enable debug logging */
|
|
204
|
+
debug?: boolean
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// ─── Constants ────────────────────────────────────────────────────────────────
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Default Winternitz program ID (placeholder - update with actual deployment)
|
|
211
|
+
*/
|
|
212
|
+
export const WINTERNITZ_PROGRAM_ID = new PublicKey(
|
|
213
|
+
'WntrVt1111111111111111111111111111111111111'
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Vault account size
|
|
218
|
+
*/
|
|
219
|
+
export const VAULT_ACCOUNT_SIZE = 256
|
|
220
|
+
|
|
221
|
+
// ─── WinternitzVaultAdapter ───────────────────────────────────────────────────
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Quantum-resistant vault adapter
|
|
225
|
+
*
|
|
226
|
+
* Integrates Winternitz vaults with SIP privacy primitives.
|
|
227
|
+
*/
|
|
228
|
+
export class WinternitzVaultAdapter {
|
|
229
|
+
private connection: Connection
|
|
230
|
+
private programId: PublicKey
|
|
231
|
+
private keyManager: WotsKeyManager
|
|
232
|
+
private debug: boolean
|
|
233
|
+
|
|
234
|
+
constructor(config: WinternitzVaultConfig) {
|
|
235
|
+
this.connection = config.connection
|
|
236
|
+
this.programId = config.programId ?? WINTERNITZ_PROGRAM_ID
|
|
237
|
+
this.keyManager = new WotsKeyManager()
|
|
238
|
+
this.debug = config.debug ?? false
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Generate a fresh Winternitz keypair for a new vault
|
|
243
|
+
*/
|
|
244
|
+
generateKeypair(): WinternitzKeypair {
|
|
245
|
+
const keypair = generateWinternitzKeypair()
|
|
246
|
+
this.keyManager.register(keypair)
|
|
247
|
+
return keypair
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Derive vault PDA from merkle root
|
|
252
|
+
*/
|
|
253
|
+
deriveVaultAddress(merkleRoot: Uint8Array): PublicKey {
|
|
254
|
+
const [vaultAddress] = PublicKey.findProgramAddressSync(
|
|
255
|
+
[merkleRoot],
|
|
256
|
+
this.programId
|
|
257
|
+
)
|
|
258
|
+
return vaultAddress
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Open a new shielded vault (mock implementation)
|
|
263
|
+
*
|
|
264
|
+
* In production, this would interact with the deployed Winternitz program.
|
|
265
|
+
*/
|
|
266
|
+
async openVault(params: OpenVaultParams): Promise<{
|
|
267
|
+
vault: ShieldedVault
|
|
268
|
+
wotsKeypair: WinternitzKeypair
|
|
269
|
+
}> {
|
|
270
|
+
const {
|
|
271
|
+
amount,
|
|
272
|
+
recipientMetaAddress,
|
|
273
|
+
viewingKey,
|
|
274
|
+
payer: _payer,
|
|
275
|
+
signTransaction: _signTransaction,
|
|
276
|
+
} = params
|
|
277
|
+
|
|
278
|
+
// Note: payer and signTransaction are used in production to send transactions
|
|
279
|
+
void _payer
|
|
280
|
+
void _signTransaction
|
|
281
|
+
|
|
282
|
+
// Generate WOTS keypair
|
|
283
|
+
const wotsKeypair = this.generateKeypair()
|
|
284
|
+
const vaultAddress = this.deriveVaultAddress(wotsKeypair.merkleRoot)
|
|
285
|
+
|
|
286
|
+
// Generate stealth address for recipient
|
|
287
|
+
const stealthAddress = this.generateMockStealthAddress(recipientMetaAddress)
|
|
288
|
+
|
|
289
|
+
// Generate Pedersen commitment
|
|
290
|
+
const commitment = this.generateMockCommitment(amount)
|
|
291
|
+
|
|
292
|
+
// Encrypt metadata if viewing key provided
|
|
293
|
+
let encryptedMetadata: ShieldedVault['encryptedMetadata']
|
|
294
|
+
if (viewingKey) {
|
|
295
|
+
encryptedMetadata = this.encryptMetadata(
|
|
296
|
+
{ balance: amount, blindingFactor: commitment.blindingFactor, timestamp: Date.now() },
|
|
297
|
+
viewingKey
|
|
298
|
+
)
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// Create vault (mock - would send transaction in production)
|
|
302
|
+
if (this.debug) {
|
|
303
|
+
console.log(`[WinternitzVault] Opening vault at ${vaultAddress.toBase58()}`)
|
|
304
|
+
console.log(`[WinternitzVault] Amount: ${amount} lamports`)
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// In production: Build and send transaction to Winternitz program
|
|
308
|
+
// const ix = WinternitzProgram.openVault({ merkleRoot, lamports: amount })
|
|
309
|
+
// const tx = new Transaction().add(ix)
|
|
310
|
+
// await this.sendTransaction(tx, signTransaction)
|
|
311
|
+
|
|
312
|
+
const vault: ShieldedVault = {
|
|
313
|
+
wotsMerkleRoot: wotsKeypair.merkleRoot,
|
|
314
|
+
vaultAddress,
|
|
315
|
+
balance: amount,
|
|
316
|
+
stealthAddress,
|
|
317
|
+
balanceCommitment: commitment,
|
|
318
|
+
encryptedMetadata,
|
|
319
|
+
status: 'active',
|
|
320
|
+
createdAt: Date.now(),
|
|
321
|
+
chain: 'solana',
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
return { vault, wotsKeypair }
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* Split vault into two destinations
|
|
329
|
+
*/
|
|
330
|
+
async splitVault(params: SplitVaultParams): Promise<{
|
|
331
|
+
splitVault: ShieldedVault
|
|
332
|
+
refundVault: ShieldedVault
|
|
333
|
+
signature: WotsSignature
|
|
334
|
+
}> {
|
|
335
|
+
const {
|
|
336
|
+
vault,
|
|
337
|
+
splitAmount,
|
|
338
|
+
splitRecipient,
|
|
339
|
+
refundRecipient,
|
|
340
|
+
wotsPrivateKey,
|
|
341
|
+
viewingKey,
|
|
342
|
+
payer,
|
|
343
|
+
signTransaction,
|
|
344
|
+
} = params
|
|
345
|
+
|
|
346
|
+
// Validate
|
|
347
|
+
if (vault.status !== 'active') {
|
|
348
|
+
throw new Error('Vault is not active')
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
if (splitAmount > vault.balance) {
|
|
352
|
+
throw new Error(`Split amount ${splitAmount} exceeds balance ${vault.balance}`)
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// Check key not already used
|
|
356
|
+
if (!this.keyManager.canUse(vault.wotsMerkleRoot)) {
|
|
357
|
+
throw new Error('WOTS key already used - cannot split vault')
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// Create split vault
|
|
361
|
+
const splitResult = await this.openVault({
|
|
362
|
+
amount: splitAmount,
|
|
363
|
+
recipientMetaAddress: splitRecipient,
|
|
364
|
+
viewingKey,
|
|
365
|
+
payer,
|
|
366
|
+
signTransaction,
|
|
367
|
+
})
|
|
368
|
+
|
|
369
|
+
// Create refund vault
|
|
370
|
+
const refundAmount = vault.balance - splitAmount
|
|
371
|
+
const refundResult = await this.openVault({
|
|
372
|
+
amount: refundAmount,
|
|
373
|
+
recipientMetaAddress: refundRecipient,
|
|
374
|
+
viewingKey,
|
|
375
|
+
payer,
|
|
376
|
+
signTransaction,
|
|
377
|
+
})
|
|
378
|
+
|
|
379
|
+
// Sign split message with WOTS
|
|
380
|
+
const message = this.buildSplitMessage(
|
|
381
|
+
splitResult.vault.vaultAddress,
|
|
382
|
+
refundResult.vault.vaultAddress,
|
|
383
|
+
splitAmount
|
|
384
|
+
)
|
|
385
|
+
|
|
386
|
+
// Mark key as used BEFORE signing (critical for security)
|
|
387
|
+
await this.keyManager.markUsed(
|
|
388
|
+
vault.wotsMerkleRoot,
|
|
389
|
+
`split:${splitResult.vault.vaultAddress.toBase58()}`
|
|
390
|
+
)
|
|
391
|
+
|
|
392
|
+
const signature = wotsSign(wotsPrivateKey, message)
|
|
393
|
+
|
|
394
|
+
if (this.debug) {
|
|
395
|
+
console.log(`[WinternitzVault] Split vault: ${splitAmount} + ${refundAmount}`)
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// Mark original vault as spent
|
|
399
|
+
vault.status = 'spent'
|
|
400
|
+
|
|
401
|
+
return {
|
|
402
|
+
splitVault: splitResult.vault,
|
|
403
|
+
refundVault: refundResult.vault,
|
|
404
|
+
signature,
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* Close vault and send all funds to recipient
|
|
410
|
+
*/
|
|
411
|
+
async closeVault(params: CloseVaultParams): Promise<{
|
|
412
|
+
recipientVault: ShieldedVault
|
|
413
|
+
signature: WotsSignature
|
|
414
|
+
}> {
|
|
415
|
+
const {
|
|
416
|
+
vault,
|
|
417
|
+
recipient,
|
|
418
|
+
wotsPrivateKey,
|
|
419
|
+
viewingKey,
|
|
420
|
+
payer,
|
|
421
|
+
signTransaction,
|
|
422
|
+
} = params
|
|
423
|
+
|
|
424
|
+
// Validate
|
|
425
|
+
if (vault.status !== 'active') {
|
|
426
|
+
throw new Error('Vault is not active')
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
if (!this.keyManager.canUse(vault.wotsMerkleRoot)) {
|
|
430
|
+
throw new Error('WOTS key already used - cannot close vault')
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
// Create recipient vault
|
|
434
|
+
const recipientResult = await this.openVault({
|
|
435
|
+
amount: vault.balance,
|
|
436
|
+
recipientMetaAddress: recipient,
|
|
437
|
+
viewingKey,
|
|
438
|
+
payer,
|
|
439
|
+
signTransaction,
|
|
440
|
+
})
|
|
441
|
+
|
|
442
|
+
// Sign close message
|
|
443
|
+
const message = this.buildCloseMessage(recipientResult.vault.vaultAddress)
|
|
444
|
+
|
|
445
|
+
// Mark key as used
|
|
446
|
+
await this.keyManager.markUsed(
|
|
447
|
+
vault.wotsMerkleRoot,
|
|
448
|
+
`close:${recipientResult.vault.vaultAddress.toBase58()}`
|
|
449
|
+
)
|
|
450
|
+
|
|
451
|
+
const signature = wotsSign(wotsPrivateKey, message)
|
|
452
|
+
|
|
453
|
+
if (this.debug) {
|
|
454
|
+
console.log(`[WinternitzVault] Closed vault: ${vault.balance} lamports`)
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
// Mark original vault as spent
|
|
458
|
+
vault.status = 'spent'
|
|
459
|
+
|
|
460
|
+
return {
|
|
461
|
+
recipientVault: recipientResult.vault,
|
|
462
|
+
signature,
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* Scan for vaults belonging to a keypair
|
|
468
|
+
*/
|
|
469
|
+
scanVaults(params: ScanVaultsParams): ShieldedVault[] {
|
|
470
|
+
const { spendingPrivateKey, viewingPrivateKey, vaults } = params
|
|
471
|
+
|
|
472
|
+
const matchedVaults: ShieldedVault[] = []
|
|
473
|
+
|
|
474
|
+
for (const vault of vaults) {
|
|
475
|
+
// Check view tag first (97% rejection rate)
|
|
476
|
+
if (!this.checkViewTag(vault.stealthAddress, viewingPrivateKey)) {
|
|
477
|
+
continue
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
// Full stealth check
|
|
481
|
+
if (this.checkStealthOwnership(vault.stealthAddress, spendingPrivateKey, viewingPrivateKey)) {
|
|
482
|
+
matchedVaults.push(vault)
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
return matchedVaults
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
/**
|
|
490
|
+
* Verify signature for a vault operation
|
|
491
|
+
*/
|
|
492
|
+
verifySignature(
|
|
493
|
+
publicKey: Uint8Array,
|
|
494
|
+
message: Uint8Array,
|
|
495
|
+
signature: WotsSignature
|
|
496
|
+
): boolean {
|
|
497
|
+
return wotsVerify(publicKey, message, signature)
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/**
|
|
501
|
+
* Get key manager for tracking WOTS key usage
|
|
502
|
+
*/
|
|
503
|
+
getKeyManager(): WotsKeyManager {
|
|
504
|
+
return this.keyManager
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
/**
|
|
508
|
+
* Estimate transaction cost
|
|
509
|
+
*/
|
|
510
|
+
estimateOpenCost(): bigint {
|
|
511
|
+
// Rent for vault account + transaction fee
|
|
512
|
+
const rentExemption = 890880n // ~0.00089 SOL for 256 bytes
|
|
513
|
+
const txFee = 5000n
|
|
514
|
+
return rentExemption + txFee
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
// ─── Private Helpers ──────────────────────────────────────────────────────────
|
|
518
|
+
|
|
519
|
+
private generateMockStealthAddress(_metaAddress: {
|
|
520
|
+
spendingPublicKey: HexString
|
|
521
|
+
viewingPublicKey: HexString
|
|
522
|
+
}): ShieldedVault['stealthAddress'] {
|
|
523
|
+
// In production, use generateEd25519StealthAddress with _metaAddress
|
|
524
|
+
const ephemeral = keccak_256(new TextEncoder().encode(Date.now().toString()))
|
|
525
|
+
return {
|
|
526
|
+
address: `0x${Buffer.from(ephemeral).toString('hex')}`,
|
|
527
|
+
ephemeralPublicKey: `0x${Buffer.from(ephemeral).toString('hex')}`,
|
|
528
|
+
viewTag: ephemeral[0],
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
private generateMockCommitment(amount: bigint): {
|
|
533
|
+
value: HexString
|
|
534
|
+
blindingFactor: HexString
|
|
535
|
+
} {
|
|
536
|
+
// In production, use commit() from crypto module
|
|
537
|
+
const blinding = keccak_256(new TextEncoder().encode(Math.random().toString()))
|
|
538
|
+
const commitment = keccak_256(
|
|
539
|
+
new Uint8Array([...this.bigintToBytes(amount), ...blinding])
|
|
540
|
+
)
|
|
541
|
+
return {
|
|
542
|
+
value: `0x${Buffer.from(commitment).toString('hex')}`,
|
|
543
|
+
blindingFactor: `0x${Buffer.from(blinding).toString('hex')}`,
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
private encryptMetadata(
|
|
548
|
+
metadata: Partial<ShieldedVaultMetadata>,
|
|
549
|
+
viewingKey: HexString
|
|
550
|
+
): ShieldedVault['encryptedMetadata'] {
|
|
551
|
+
// In production, use XChaCha20-Poly1305
|
|
552
|
+
const data = JSON.stringify(metadata)
|
|
553
|
+
const nonce = keccak_256(new TextEncoder().encode(Date.now().toString())).slice(0, 24)
|
|
554
|
+
const ciphertext = new TextEncoder().encode(data) // Mock - not actually encrypted
|
|
555
|
+
|
|
556
|
+
return {
|
|
557
|
+
ciphertext: `0x${Buffer.from(ciphertext).toString('hex')}`,
|
|
558
|
+
nonce: `0x${Buffer.from(nonce).toString('hex')}`,
|
|
559
|
+
viewingKeyHash: `0x${Buffer.from(keccak_256(this.hexToBytes(viewingKey))).toString('hex')}`,
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
private buildSplitMessage(
|
|
564
|
+
splitVault: PublicKey,
|
|
565
|
+
refundVault: PublicKey,
|
|
566
|
+
amount: bigint
|
|
567
|
+
): Uint8Array {
|
|
568
|
+
const data = new Uint8Array(96)
|
|
569
|
+
data.set(splitVault.toBytes(), 0)
|
|
570
|
+
data.set(refundVault.toBytes(), 32)
|
|
571
|
+
data.set(this.bigintToBytes(amount), 64)
|
|
572
|
+
return keccak_256(data)
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
private buildCloseMessage(recipientVault: PublicKey): Uint8Array {
|
|
576
|
+
return keccak_256(recipientVault.toBytes())
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
private checkViewTag(
|
|
580
|
+
_stealthAddress: ShieldedVault['stealthAddress'],
|
|
581
|
+
_viewingKey: HexString
|
|
582
|
+
): boolean {
|
|
583
|
+
// Mock view tag check - in production, verify view tag matches
|
|
584
|
+
return true
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
private checkStealthOwnership(
|
|
588
|
+
_stealthAddress: ShieldedVault['stealthAddress'],
|
|
589
|
+
_spendingKey: HexString,
|
|
590
|
+
_viewingKey: HexString
|
|
591
|
+
): boolean {
|
|
592
|
+
// Mock ownership check - in production, use checkEd25519StealthAddress
|
|
593
|
+
return true
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
private bigintToBytes(value: bigint): Uint8Array {
|
|
597
|
+
const bytes = new Uint8Array(32)
|
|
598
|
+
let v = value
|
|
599
|
+
for (let i = 31; i >= 0; i--) {
|
|
600
|
+
bytes[i] = Number(v & 0xffn)
|
|
601
|
+
v >>= 8n
|
|
602
|
+
}
|
|
603
|
+
return bytes
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
private hexToBytes(hex: HexString): Uint8Array {
|
|
607
|
+
const cleaned = hex.startsWith('0x') ? hex.slice(2) : hex
|
|
608
|
+
const bytes = new Uint8Array(cleaned.length / 2)
|
|
609
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
610
|
+
bytes[i] = parseInt(cleaned.slice(i * 2, i * 2 + 2), 16)
|
|
611
|
+
}
|
|
612
|
+
return bytes
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
// ─── Factory Function ─────────────────────────────────────────────────────────
|
|
617
|
+
|
|
618
|
+
/**
|
|
619
|
+
* Create a Winternitz vault adapter
|
|
620
|
+
*
|
|
621
|
+
* @example
|
|
622
|
+
* ```typescript
|
|
623
|
+
* const adapter = createWinternitzVaultAdapter({
|
|
624
|
+
* connection: new Connection('https://api.mainnet-beta.solana.com'),
|
|
625
|
+
* })
|
|
626
|
+
*
|
|
627
|
+
* const { vault, wotsKeypair } = await adapter.openVault({
|
|
628
|
+
* amount: 1_000_000_000n,
|
|
629
|
+
* recipientMetaAddress: { spendingPublicKey, viewingPublicKey },
|
|
630
|
+
* payer: wallet.publicKey,
|
|
631
|
+
* signTransaction: wallet.signTransaction,
|
|
632
|
+
* })
|
|
633
|
+
* ```
|
|
634
|
+
*/
|
|
635
|
+
export function createWinternitzVaultAdapter(
|
|
636
|
+
config: WinternitzVaultConfig
|
|
637
|
+
): WinternitzVaultAdapter {
|
|
638
|
+
return new WinternitzVaultAdapter(config)
|
|
639
|
+
}
|