@ghostspeak/sdk 2.0.6 → 2.0.7
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/README.md +152 -30
- package/dist/GhostSpeakClient-CWmGaM9Q.d.ts +1007 -0
- package/dist/StakingModule-C5rzuOWb.d.ts +2526 -0
- package/dist/{agent-M74TCRON.js → agent-5YLZ7DAC.js} +4 -4
- package/dist/{agent-M74TCRON.js.map → agent-5YLZ7DAC.js.map} +1 -1
- package/dist/batch-operations-45CQFEID.js +4 -0
- package/dist/batch-operations-45CQFEID.js.map +1 -0
- package/dist/browser.d.ts +45 -554
- package/dist/browser.js +15 -842
- package/dist/browser.js.map +1 -1
- package/dist/chunk-AL3HQN73.js +754 -0
- package/dist/chunk-AL3HQN73.js.map +1 -0
- package/dist/chunk-BF3IQ35I.js +284 -0
- package/dist/chunk-BF3IQ35I.js.map +1 -0
- package/dist/chunk-BQDGRTVP.js +168 -0
- package/dist/chunk-BQDGRTVP.js.map +1 -0
- package/dist/chunk-C5CDA3WX.js +7314 -0
- package/dist/chunk-C5CDA3WX.js.map +1 -0
- package/dist/chunk-E3FD2CNY.js +1869 -0
- package/dist/chunk-E3FD2CNY.js.map +1 -0
- package/dist/{chunk-F3DZMBUA.js → chunk-G7S6B6WB.js} +327 -493
- package/dist/chunk-G7S6B6WB.js.map +1 -0
- package/dist/chunk-IHVDQ4YI.js +4231 -0
- package/dist/chunk-IHVDQ4YI.js.map +1 -0
- package/dist/chunk-JV2SWONF.js +98 -0
- package/dist/chunk-JV2SWONF.js.map +1 -0
- package/dist/chunk-KB6CKIUK.js +231 -0
- package/dist/chunk-KB6CKIUK.js.map +1 -0
- package/dist/chunk-S74EH3KD.js +7890 -0
- package/dist/chunk-S74EH3KD.js.map +1 -0
- package/dist/chunk-SFTSZ3LC.js +156 -0
- package/dist/chunk-SFTSZ3LC.js.map +1 -0
- package/dist/chunk-SKMJJ3Q6.js +125 -0
- package/dist/chunk-SKMJJ3Q6.js.map +1 -0
- package/dist/chunk-SZGFSCNU.js +3682 -0
- package/dist/chunk-SZGFSCNU.js.map +1 -0
- package/dist/chunk-TTB4OS2D.js +69 -0
- package/dist/chunk-TTB4OS2D.js.map +1 -0
- package/dist/chunk-UP2VWCW5.js +33 -0
- package/dist/{chunk-NSBPE2FW.js.map → chunk-UP2VWCW5.js.map} +1 -1
- package/dist/{chunk-UJUGGLMT.js → chunk-VQZQCHUT.js} +5 -5
- package/dist/{chunk-UJUGGLMT.js.map → chunk-VQZQCHUT.js.map} +1 -1
- package/dist/client.d.ts +5 -4
- package/dist/client.js +11 -10
- package/dist/createAgentAuthorization-ULG47ZJI.js +5 -0
- package/dist/createAgentAuthorization-ULG47ZJI.js.map +1 -0
- package/dist/credentials.js +1 -1
- package/dist/crypto.js +2 -2
- package/dist/errors.js +1 -1
- package/dist/feature-flags-B1g0DCPe.d.ts +1181 -0
- package/dist/generated-EG5USUFG.js +9 -0
- package/dist/{generated-VNLHMR6Y.js.map → generated-EG5USUFG.js.map} +1 -1
- package/dist/{ghostspeak_wasm-SB2RPJ3D.js → ghostspeak_wasm-F227HOSM.js} +3 -3
- package/dist/{ghostspeak_wasm-SB2RPJ3D.js.map → ghostspeak_wasm-F227HOSM.js.map} +1 -1
- package/dist/index.d.ts +1209 -1506
- package/dist/index.js +600 -3532
- package/dist/index.js.map +1 -1
- package/dist/metafile-esm.json +1 -1
- package/dist/minimal/core-minimal.d.ts +2383 -1264
- package/dist/minimal/core-minimal.js +9 -9
- package/dist/minimal/core-minimal.js.map +1 -1
- package/dist/nacl-fast-W5BJ3KZ2.js +2229 -0
- package/dist/nacl-fast-W5BJ3KZ2.js.map +1 -0
- package/dist/pda-4KP7CURF.js +4 -0
- package/dist/pda-4KP7CURF.js.map +1 -0
- package/dist/pda-Ce7VYg4T.d.ts +25 -0
- package/dist/reputation-types-Yebf0Rm_.d.ts +1071 -0
- package/dist/revokeAuthorization-OK7E7OK3.js +5 -0
- package/dist/revokeAuthorization-OK7E7OK3.js.map +1 -0
- package/dist/signature-verification-DGxR4aYQ.d.ts +448 -0
- package/dist/types.js +1 -1
- package/dist/updateReputationWithAuth-Y4ONEVSP.js +5 -0
- package/dist/updateReputationWithAuth-Y4ONEVSP.js.map +1 -0
- package/dist/utils.d.ts +69 -203
- package/dist/utils.js +15 -153
- package/dist/utils.js.map +1 -1
- package/package.json +24 -31
- package/dist/.tsbuildinfo +0 -1
- package/dist/GhostSpeakClient-D_66Uzsf.d.ts +0 -707
- package/dist/GovernanceModule-DQYYys-H.d.ts +0 -1766
- package/dist/chunk-APCKGD23.js +0 -1328
- package/dist/chunk-APCKGD23.js.map +0 -1
- package/dist/chunk-ASQXX4IT.js +0 -572
- package/dist/chunk-ASQXX4IT.js.map +0 -1
- package/dist/chunk-COGZFWOT.js +0 -19657
- package/dist/chunk-COGZFWOT.js.map +0 -1
- package/dist/chunk-F3DZMBUA.js.map +0 -1
- package/dist/chunk-GMHIUK2R.js +0 -7526
- package/dist/chunk-GMHIUK2R.js.map +0 -1
- package/dist/chunk-IAWBZYPE.js +0 -356
- package/dist/chunk-IAWBZYPE.js.map +0 -1
- package/dist/chunk-NSBPE2FW.js +0 -15
- package/dist/chunk-OWYHJG6H.js +0 -13311
- package/dist/chunk-OWYHJG6H.js.map +0 -1
- package/dist/chunk-RDDPOFR5.js +0 -3
- package/dist/chunk-RDDPOFR5.js.map +0 -1
- package/dist/chunk-RERCHKZP.js +0 -35
- package/dist/chunk-RERCHKZP.js.map +0 -1
- package/dist/chunk-TVVGXYCI.js +0 -2887
- package/dist/chunk-TVVGXYCI.js.map +0 -1
- package/dist/chunk-ZGP5552B.js +0 -377
- package/dist/chunk-ZGP5552B.js.map +0 -1
- package/dist/chunk-ZWOYNHVK.js +0 -196
- package/dist/chunk-ZWOYNHVK.js.map +0 -1
- package/dist/dist/.tsbuildinfo +0 -1
- package/dist/elgamal-VZLWB3XK.js +0 -5
- package/dist/elgamal-VZLWB3XK.js.map +0 -1
- package/dist/feature-flags-V722ZuXO.d.ts +0 -3512
- package/dist/generated-VNLHMR6Y.js +0 -5
- package/dist/ipfs-types-BOt9ZNg4.d.ts +0 -592
- package/dist/multisigConfig-BzEhy6jy.d.ts +0 -58
- package/dist/pda-B_nS8SbD.d.ts +0 -114
- package/dist/pda-S4BFJVGE.js +0 -4
- package/dist/pda-S4BFJVGE.js.map +0 -1
- package/dist/system-addresses-BFNLEbFx.d.ts +0 -857
- package/dist/token-2022-rpc-RALH4RK7.js +0 -593
- package/dist/token-2022-rpc-RALH4RK7.js.map +0 -1
package/dist/chunk-IAWBZYPE.js
DELETED
|
@@ -1,356 +0,0 @@
|
|
|
1
|
-
import { ed25519 } from '@noble/curves/ed25519';
|
|
2
|
-
import { sha256 } from '@noble/hashes/sha256';
|
|
3
|
-
import { bytesToNumberLE, randomBytes, bytesToHex } from '@noble/curves/abstract/utils';
|
|
4
|
-
import { getAddressEncoder } from '@solana/kit';
|
|
5
|
-
|
|
6
|
-
// src/utils/elgamal.ts
|
|
7
|
-
var MAX_DECRYPTABLE_VALUE = 4294967295n;
|
|
8
|
-
var G = ed25519.ExtendedPoint.BASE;
|
|
9
|
-
var hash = (data) => sha256(data);
|
|
10
|
-
function numberToBytesLE(n, length) {
|
|
11
|
-
const bytes = new Uint8Array(length);
|
|
12
|
-
let temp = n;
|
|
13
|
-
for (let i = 0; i < length; i++) {
|
|
14
|
-
bytes[i] = Number(temp & 0xffn);
|
|
15
|
-
temp >>= 8n;
|
|
16
|
-
}
|
|
17
|
-
return bytes;
|
|
18
|
-
}
|
|
19
|
-
function generateElGamalKeypair(seed) {
|
|
20
|
-
const secretKey = seed ? hash(seed).slice(0, 32) : randomBytes(32);
|
|
21
|
-
secretKey[0] &= 248;
|
|
22
|
-
secretKey[31] &= 127;
|
|
23
|
-
secretKey[31] |= 64;
|
|
24
|
-
const scalarValue = bytesToNumberLE(secretKey) % ed25519.CURVE.n;
|
|
25
|
-
const publicKey = G.multiply(scalarValue).toRawBytes();
|
|
26
|
-
return { publicKey, secretKey };
|
|
27
|
-
}
|
|
28
|
-
function deriveElGamalKeypair(signer, tokenAccount) {
|
|
29
|
-
const message = new TextEncoder().encode(`elgamal:${tokenAccount}`);
|
|
30
|
-
const signerBytes = getAddressEncoder().encode(signer.address);
|
|
31
|
-
const combined = new Uint8Array(signerBytes.length + message.length);
|
|
32
|
-
combined.set(signerBytes);
|
|
33
|
-
combined.set(message, signerBytes.length);
|
|
34
|
-
const seed = hash(combined);
|
|
35
|
-
return generateElGamalKeypair(seed);
|
|
36
|
-
}
|
|
37
|
-
function encryptAmount(amount, pubkey) {
|
|
38
|
-
const result = encryptAmountWithRandomness(amount, pubkey);
|
|
39
|
-
return result.ciphertext;
|
|
40
|
-
}
|
|
41
|
-
function encryptAmountWithRandomness(amount, pubkey, providedRandomness) {
|
|
42
|
-
if (amount < 0n) {
|
|
43
|
-
throw new Error("Amount must be non-negative");
|
|
44
|
-
}
|
|
45
|
-
if (amount > MAX_DECRYPTABLE_VALUE) {
|
|
46
|
-
throw new Error(`Amount exceeds maximum decryptable value (${MAX_DECRYPTABLE_VALUE})`);
|
|
47
|
-
}
|
|
48
|
-
const randomness = providedRandomness ?? randomBytes(32);
|
|
49
|
-
randomness[0] &= 248;
|
|
50
|
-
randomness[31] &= 127;
|
|
51
|
-
randomness[31] |= 64;
|
|
52
|
-
const r = bytesToNumberLE(randomness) % ed25519.CURVE.n;
|
|
53
|
-
const pubkeyPoint = ed25519.ExtendedPoint.fromHex(bytesToHex(pubkey));
|
|
54
|
-
const amountPoint = amount === 0n ? ed25519.ExtendedPoint.ZERO : G.multiply(amount);
|
|
55
|
-
const maskedAmount = amountPoint.add(pubkeyPoint.multiply(r));
|
|
56
|
-
const commitment = maskedAmount.toRawBytes();
|
|
57
|
-
const handle = G.multiply(r).toRawBytes();
|
|
58
|
-
return {
|
|
59
|
-
ciphertext: {
|
|
60
|
-
commitment: { commitment },
|
|
61
|
-
handle: { handle }
|
|
62
|
-
},
|
|
63
|
-
randomness
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
function decryptAmount(ciphertext, secretKey, maxValue = 65536n) {
|
|
67
|
-
const C = ed25519.ExtendedPoint.fromHex(bytesToHex(ciphertext.commitment.commitment));
|
|
68
|
-
const D = ed25519.ExtendedPoint.fromHex(bytesToHex(ciphertext.handle.handle));
|
|
69
|
-
const sk = bytesToNumberLE(secretKey) % ed25519.CURVE.n;
|
|
70
|
-
const decryptedPoint = C.subtract(D.multiply(sk));
|
|
71
|
-
for (let i = 0n; i <= maxValue; i++) {
|
|
72
|
-
const testPoint = i === 0n ? ed25519.ExtendedPoint.ZERO : G.multiply(i);
|
|
73
|
-
if (testPoint.equals(decryptedPoint)) {
|
|
74
|
-
return i;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
return null;
|
|
78
|
-
}
|
|
79
|
-
function decryptAmountWithLookup(ciphertext, secretKey, lookupTable) {
|
|
80
|
-
const C = ed25519.ExtendedPoint.fromHex(bytesToHex(ciphertext.commitment.commitment));
|
|
81
|
-
const D = ed25519.ExtendedPoint.fromHex(bytesToHex(ciphertext.handle.handle));
|
|
82
|
-
const sk = bytesToNumberLE(secretKey) % ed25519.CURVE.n;
|
|
83
|
-
const decryptedPoint = C.subtract(D.multiply(sk));
|
|
84
|
-
const pointHex = decryptedPoint.toHex();
|
|
85
|
-
return lookupTable.get(pointHex) ?? null;
|
|
86
|
-
}
|
|
87
|
-
function buildDecryptionLookupTable(maxValue) {
|
|
88
|
-
const lookupTable = /* @__PURE__ */ new Map();
|
|
89
|
-
for (let i = 0n; i <= maxValue; i++) {
|
|
90
|
-
const point = i === 0n ? ed25519.ExtendedPoint.ZERO : G.multiply(i);
|
|
91
|
-
lookupTable.set(point.toHex(), i);
|
|
92
|
-
}
|
|
93
|
-
return lookupTable;
|
|
94
|
-
}
|
|
95
|
-
function addCiphertexts(a, b) {
|
|
96
|
-
const Ca = ed25519.ExtendedPoint.fromHex(bytesToHex(a.commitment.commitment));
|
|
97
|
-
const Cb = ed25519.ExtendedPoint.fromHex(bytesToHex(b.commitment.commitment));
|
|
98
|
-
const Da = ed25519.ExtendedPoint.fromHex(bytesToHex(a.handle.handle));
|
|
99
|
-
const Db = ed25519.ExtendedPoint.fromHex(bytesToHex(b.handle.handle));
|
|
100
|
-
const sumCommitment = Ca.add(Cb).toRawBytes();
|
|
101
|
-
const sumHandle = Da.add(Db).toRawBytes();
|
|
102
|
-
return {
|
|
103
|
-
commitment: { commitment: sumCommitment },
|
|
104
|
-
handle: { handle: sumHandle }
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
function subtractCiphertexts(a, b) {
|
|
108
|
-
const Ca = ed25519.ExtendedPoint.fromHex(bytesToHex(a.commitment.commitment));
|
|
109
|
-
const Cb = ed25519.ExtendedPoint.fromHex(bytesToHex(b.commitment.commitment));
|
|
110
|
-
const Da = ed25519.ExtendedPoint.fromHex(bytesToHex(a.handle.handle));
|
|
111
|
-
const Db = ed25519.ExtendedPoint.fromHex(bytesToHex(b.handle.handle));
|
|
112
|
-
const diffCommitment = Ca.subtract(Cb).toRawBytes();
|
|
113
|
-
const diffHandle = Da.subtract(Db).toRawBytes();
|
|
114
|
-
return {
|
|
115
|
-
commitment: { commitment: diffCommitment },
|
|
116
|
-
handle: { handle: diffHandle }
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
function scaleCiphertext(ciphertext, scalar) {
|
|
120
|
-
if (scalar === 0n) {
|
|
121
|
-
const zeroPoint = ed25519.ExtendedPoint.ZERO;
|
|
122
|
-
return {
|
|
123
|
-
commitment: { commitment: zeroPoint.toRawBytes() },
|
|
124
|
-
handle: { handle: zeroPoint.toRawBytes() }
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
const C = ed25519.ExtendedPoint.fromHex(bytesToHex(ciphertext.commitment.commitment));
|
|
128
|
-
const D = ed25519.ExtendedPoint.fromHex(bytesToHex(ciphertext.handle.handle));
|
|
129
|
-
const scaledCommitment = C.multiply(scalar).toRawBytes();
|
|
130
|
-
const scaledHandle = D.multiply(scalar).toRawBytes();
|
|
131
|
-
return {
|
|
132
|
-
commitment: { commitment: scaledCommitment },
|
|
133
|
-
handle: { handle: scaledHandle }
|
|
134
|
-
};
|
|
135
|
-
}
|
|
136
|
-
var RANGE_PROOF_SIZE = 672;
|
|
137
|
-
function getGeneratorH() {
|
|
138
|
-
const hashInput = new TextEncoder().encode("ElGamal-Generator-H");
|
|
139
|
-
const hashOutput = hash(hashInput);
|
|
140
|
-
const scalar = bytesToNumberLE(hashOutput) % ed25519.CURVE.n;
|
|
141
|
-
return G.multiply(scalar);
|
|
142
|
-
}
|
|
143
|
-
getGeneratorH();
|
|
144
|
-
async function generateRangeProof(amount, commitment, randomness) {
|
|
145
|
-
if (amount < 0n || amount > MAX_DECRYPTABLE_VALUE) {
|
|
146
|
-
throw new Error("Amount must be in range [0, 2^32)");
|
|
147
|
-
}
|
|
148
|
-
const proof = new Uint8Array(RANGE_PROOF_SIZE);
|
|
149
|
-
const commitmentBytes = "commitment" in commitment ? commitment.commitment : new Uint8Array(32);
|
|
150
|
-
return {
|
|
151
|
-
proof,
|
|
152
|
-
commitment: commitmentBytes
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
async function verifyRangeProof(proof, _commitment) {
|
|
156
|
-
if (proof.proof.length !== RANGE_PROOF_SIZE) {
|
|
157
|
-
return false;
|
|
158
|
-
}
|
|
159
|
-
return true;
|
|
160
|
-
}
|
|
161
|
-
function generateValidityProof(ciphertext, pubkey, randomness) {
|
|
162
|
-
const r = bytesToNumberLE(randomness) % ed25519.CURVE.n;
|
|
163
|
-
const pubkeyPoint = ed25519.ExtendedPoint.fromHex(bytesToHex(pubkey));
|
|
164
|
-
const k = bytesToNumberLE(randomBytes(32)) % ed25519.CURVE.n;
|
|
165
|
-
const R1 = k === 0n ? ed25519.ExtendedPoint.ZERO : G.multiply(k);
|
|
166
|
-
const R2 = k === 0n ? ed25519.ExtendedPoint.ZERO : pubkeyPoint.multiply(k);
|
|
167
|
-
const challenge = bytesToNumberLE(hash(new Uint8Array([
|
|
168
|
-
...ciphertext.commitment.commitment,
|
|
169
|
-
...ciphertext.handle.handle,
|
|
170
|
-
...R1.toRawBytes(),
|
|
171
|
-
...R2.toRawBytes(),
|
|
172
|
-
...pubkey
|
|
173
|
-
]))) % ed25519.CURVE.n;
|
|
174
|
-
const s = (k + challenge * r) % ed25519.CURVE.n;
|
|
175
|
-
const proofData = new Uint8Array(96);
|
|
176
|
-
proofData.set(R1.toRawBytes(), 0);
|
|
177
|
-
proofData.set(R2.toRawBytes(), 32);
|
|
178
|
-
const sBytes = numberToBytesLE(s, 32);
|
|
179
|
-
proofData.set(sBytes, 64);
|
|
180
|
-
return { proof: proofData };
|
|
181
|
-
}
|
|
182
|
-
function verifyValidityProof(proof, ciphertext, pubkey) {
|
|
183
|
-
if (proof.proof.length !== 96) {
|
|
184
|
-
return false;
|
|
185
|
-
}
|
|
186
|
-
try {
|
|
187
|
-
const R1 = ed25519.ExtendedPoint.fromHex(bytesToHex(proof.proof.slice(0, 32)));
|
|
188
|
-
const R2 = ed25519.ExtendedPoint.fromHex(bytesToHex(proof.proof.slice(32, 64)));
|
|
189
|
-
const s = bytesToNumberLE(proof.proof.slice(64, 96)) % ed25519.CURVE.n;
|
|
190
|
-
const D = ed25519.ExtendedPoint.fromHex(bytesToHex(ciphertext.handle.handle));
|
|
191
|
-
const pubkeyPoint = ed25519.ExtendedPoint.fromHex(bytesToHex(pubkey));
|
|
192
|
-
void pubkeyPoint;
|
|
193
|
-
const challenge = bytesToNumberLE(hash(new Uint8Array([
|
|
194
|
-
...ciphertext.commitment.commitment,
|
|
195
|
-
...ciphertext.handle.handle,
|
|
196
|
-
...R1.toRawBytes(),
|
|
197
|
-
...R2.toRawBytes(),
|
|
198
|
-
...pubkey
|
|
199
|
-
]))) % ed25519.CURVE.n;
|
|
200
|
-
const lhs1 = s === 0n ? ed25519.ExtendedPoint.ZERO : G.multiply(s);
|
|
201
|
-
const rhs1 = R1.add(challenge === 0n ? ed25519.ExtendedPoint.ZERO : D.multiply(challenge));
|
|
202
|
-
return lhs1.equals(rhs1);
|
|
203
|
-
} catch {
|
|
204
|
-
return false;
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
function generateEqualityProof(ciphertext1, ciphertext2, randomness1, randomness2, pubkey) {
|
|
208
|
-
const r1 = bytesToNumberLE(randomness1) % ed25519.CURVE.n;
|
|
209
|
-
const r2 = bytesToNumberLE(randomness2) % ed25519.CURVE.n;
|
|
210
|
-
const rdiff = (r1 - r2 + ed25519.CURVE.n) % ed25519.CURVE.n;
|
|
211
|
-
const k = bytesToNumberLE(randomBytes(32)) % ed25519.CURVE.n;
|
|
212
|
-
const C1 = ed25519.ExtendedPoint.fromHex(bytesToHex(ciphertext1.commitment.commitment));
|
|
213
|
-
const C2 = ed25519.ExtendedPoint.fromHex(bytesToHex(ciphertext2.commitment.commitment));
|
|
214
|
-
const D1 = ed25519.ExtendedPoint.fromHex(bytesToHex(ciphertext1.handle.handle));
|
|
215
|
-
const D2 = ed25519.ExtendedPoint.fromHex(bytesToHex(ciphertext2.handle.handle));
|
|
216
|
-
const Cdiff = C1.subtract(C2);
|
|
217
|
-
const Ddiff = D1.subtract(D2);
|
|
218
|
-
const P = pubkey ? ed25519.ExtendedPoint.fromHex(bytesToHex(pubkey)) : null;
|
|
219
|
-
const R1 = k === 0n ? ed25519.ExtendedPoint.ZERO : G.multiply(k);
|
|
220
|
-
const R2 = P && k !== 0n ? P.multiply(k) : ed25519.ExtendedPoint.ZERO;
|
|
221
|
-
const challenge = bytesToNumberLE(sha256(new Uint8Array([
|
|
222
|
-
...ciphertext1.commitment.commitment,
|
|
223
|
-
...ciphertext1.handle.handle,
|
|
224
|
-
...ciphertext2.commitment.commitment,
|
|
225
|
-
...ciphertext2.handle.handle,
|
|
226
|
-
...R1.toRawBytes(),
|
|
227
|
-
...Cdiff.toRawBytes(),
|
|
228
|
-
...Ddiff.toRawBytes()
|
|
229
|
-
]))) % ed25519.CURVE.n;
|
|
230
|
-
const s = (k + challenge * rdiff) % ed25519.CURVE.n;
|
|
231
|
-
const proofData = new Uint8Array(96);
|
|
232
|
-
let offset = 0;
|
|
233
|
-
proofData.set(R1.toRawBytes(), offset);
|
|
234
|
-
offset += 32;
|
|
235
|
-
const scalarBytes = new Uint8Array(32);
|
|
236
|
-
for (let i = 0; i < 32; i++) {
|
|
237
|
-
scalarBytes[i] = Number(s >> BigInt(i * 8) & 0xffn);
|
|
238
|
-
}
|
|
239
|
-
proofData.set(scalarBytes, offset);
|
|
240
|
-
offset += 32;
|
|
241
|
-
proofData.set(R2.toRawBytes(), offset);
|
|
242
|
-
return { proof: proofData };
|
|
243
|
-
}
|
|
244
|
-
function verifyEqualityProof(proof, ciphertext1, ciphertext2, pubkey) {
|
|
245
|
-
if (proof.proof.length !== 96) {
|
|
246
|
-
return false;
|
|
247
|
-
}
|
|
248
|
-
try {
|
|
249
|
-
let offset = 0;
|
|
250
|
-
const R1 = ed25519.ExtendedPoint.fromHex(bytesToHex(proof.proof.slice(offset, offset + 32)));
|
|
251
|
-
offset += 32;
|
|
252
|
-
const s = bytesToNumberLE(proof.proof.slice(offset, offset + 32)) % ed25519.CURVE.n;
|
|
253
|
-
offset += 32;
|
|
254
|
-
const R2 = ed25519.ExtendedPoint.fromHex(bytesToHex(proof.proof.slice(offset, offset + 32)));
|
|
255
|
-
const C1 = ed25519.ExtendedPoint.fromHex(bytesToHex(ciphertext1.commitment.commitment));
|
|
256
|
-
const C2 = ed25519.ExtendedPoint.fromHex(bytesToHex(ciphertext2.commitment.commitment));
|
|
257
|
-
const D1 = ed25519.ExtendedPoint.fromHex(bytesToHex(ciphertext1.handle.handle));
|
|
258
|
-
const D2 = ed25519.ExtendedPoint.fromHex(bytesToHex(ciphertext2.handle.handle));
|
|
259
|
-
const Cdiff = C1.subtract(C2);
|
|
260
|
-
const Ddiff = D1.subtract(D2);
|
|
261
|
-
const P = pubkey ? ed25519.ExtendedPoint.fromHex(bytesToHex(pubkey)) : null;
|
|
262
|
-
const challenge = bytesToNumberLE(sha256(new Uint8Array([
|
|
263
|
-
...ciphertext1.commitment.commitment,
|
|
264
|
-
...ciphertext1.handle.handle,
|
|
265
|
-
...ciphertext2.commitment.commitment,
|
|
266
|
-
...ciphertext2.handle.handle,
|
|
267
|
-
...R1.toRawBytes(),
|
|
268
|
-
...Cdiff.toRawBytes(),
|
|
269
|
-
...Ddiff.toRawBytes()
|
|
270
|
-
]))) % ed25519.CURVE.n;
|
|
271
|
-
const lhs1 = s === 0n ? ed25519.ExtendedPoint.ZERO : G.multiply(s);
|
|
272
|
-
const rhs1 = R1.add(challenge === 0n ? ed25519.ExtendedPoint.ZERO : Ddiff.multiply(challenge));
|
|
273
|
-
if (!lhs1.equals(rhs1)) {
|
|
274
|
-
return false;
|
|
275
|
-
}
|
|
276
|
-
if (P) {
|
|
277
|
-
const lhs2 = s === 0n ? ed25519.ExtendedPoint.ZERO : P.multiply(s);
|
|
278
|
-
const rhs2 = R2.add(challenge === 0n ? ed25519.ExtendedPoint.ZERO : Cdiff.multiply(challenge));
|
|
279
|
-
return lhs2.equals(rhs2);
|
|
280
|
-
}
|
|
281
|
-
return true;
|
|
282
|
-
} catch {
|
|
283
|
-
return false;
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
function isValidCiphertext(ciphertext) {
|
|
287
|
-
try {
|
|
288
|
-
ed25519.ExtendedPoint.fromHex(bytesToHex(ciphertext.commitment.commitment));
|
|
289
|
-
ed25519.ExtendedPoint.fromHex(bytesToHex(ciphertext.handle.handle));
|
|
290
|
-
return true;
|
|
291
|
-
} catch {
|
|
292
|
-
return false;
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
function reRandomizeCiphertext(ciphertext, pubkey) {
|
|
296
|
-
const zeroEncryption = encryptAmount(0n, pubkey);
|
|
297
|
-
return addCiphertexts(ciphertext, zeroEncryption);
|
|
298
|
-
}
|
|
299
|
-
function serializeCiphertext(ciphertext) {
|
|
300
|
-
const bytes = new Uint8Array(64);
|
|
301
|
-
bytes.set(ciphertext.commitment.commitment, 0);
|
|
302
|
-
bytes.set(ciphertext.handle.handle, 32);
|
|
303
|
-
return bytes;
|
|
304
|
-
}
|
|
305
|
-
function deserializeCiphertext(bytes) {
|
|
306
|
-
if (bytes.length !== 64) {
|
|
307
|
-
throw new Error("Invalid ciphertext length");
|
|
308
|
-
}
|
|
309
|
-
return {
|
|
310
|
-
commitment: { commitment: bytes.slice(0, 32) },
|
|
311
|
-
handle: { handle: bytes.slice(32, 64) }
|
|
312
|
-
};
|
|
313
|
-
}
|
|
314
|
-
async function generateTransferProof(sourceBalance, amount, sourceKeypair, destPubkey) {
|
|
315
|
-
const destEncryption = encryptAmountWithRandomness(amount, destPubkey);
|
|
316
|
-
const destCiphertext = destEncryption.ciphertext;
|
|
317
|
-
const sourceEncryption = encryptAmountWithRandomness(amount, sourceKeypair.publicKey);
|
|
318
|
-
const sourceTransferCiphertext = sourceEncryption.ciphertext;
|
|
319
|
-
const equalityProof = generateEqualityProof(
|
|
320
|
-
destCiphertext,
|
|
321
|
-
sourceTransferCiphertext,
|
|
322
|
-
destEncryption.randomness,
|
|
323
|
-
sourceEncryption.randomness,
|
|
324
|
-
destPubkey
|
|
325
|
-
);
|
|
326
|
-
const validityProof = generateValidityProof(
|
|
327
|
-
destCiphertext,
|
|
328
|
-
destPubkey,
|
|
329
|
-
destEncryption.randomness
|
|
330
|
-
);
|
|
331
|
-
const newSourceBalance = subtractCiphertexts(sourceBalance, sourceTransferCiphertext);
|
|
332
|
-
const currentBalance = decryptAmount(sourceBalance, sourceKeypair.secretKey, MAX_DECRYPTABLE_VALUE * 100n);
|
|
333
|
-
if (currentBalance === null) {
|
|
334
|
-
throw new Error("Could not decrypt source balance to generate range proof");
|
|
335
|
-
}
|
|
336
|
-
const newBalanceValue = currentBalance - amount;
|
|
337
|
-
if (newBalanceValue < 0n) {
|
|
338
|
-
throw new Error("Insufficient balance");
|
|
339
|
-
}
|
|
340
|
-
const rangeProof = await generateRangeProof(newBalanceValue, newSourceBalance.commitment);
|
|
341
|
-
return {
|
|
342
|
-
transferProof: {
|
|
343
|
-
encryptedTransferAmount: serializeCiphertext(destCiphertext),
|
|
344
|
-
newSourceCommitment: newSourceBalance.commitment.commitment,
|
|
345
|
-
equalityProof: equalityProof.proof,
|
|
346
|
-
validityProof: validityProof.proof,
|
|
347
|
-
rangeProof: rangeProof.proof
|
|
348
|
-
},
|
|
349
|
-
newSourceBalance,
|
|
350
|
-
destCiphertext
|
|
351
|
-
};
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
export { MAX_DECRYPTABLE_VALUE, addCiphertexts, buildDecryptionLookupTable, decryptAmount, decryptAmountWithLookup, deriveElGamalKeypair, deserializeCiphertext, encryptAmount, encryptAmountWithRandomness, generateElGamalKeypair, generateEqualityProof, generateRangeProof, generateTransferProof, generateValidityProof, isValidCiphertext, reRandomizeCiphertext, scaleCiphertext, serializeCiphertext, subtractCiphertexts, verifyEqualityProof, verifyRangeProof, verifyValidityProof };
|
|
355
|
-
//# sourceMappingURL=chunk-IAWBZYPE.js.map
|
|
356
|
-
//# sourceMappingURL=chunk-IAWBZYPE.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/elgamal.ts"],"names":[],"mappings":"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","file":"chunk-IAWBZYPE.js","sourcesContent":["/**\n * ElGamal Encryption Implementation\n * \n * Implements twisted ElGamal encryption over curve25519 for\n * client-side privacy features.\n * \n * Key features:\n * - Twisted ElGamal with Pedersen commitments\n * - Homomorphic addition/subtraction of ciphertexts\n * - Efficient decryption for small values (up to 32 bits)\n */\n\nimport './text-encoder-polyfill.js'\nimport { ed25519 } from '@noble/curves/ed25519'\nimport { sha256 } from '@noble/hashes/sha256'\nimport { randomBytes, bytesToNumberLE, bytesToHex } from '@noble/curves/abstract/utils'\nimport type { Address } from '@solana/addresses'\nimport { getAddressEncoder } from '@solana/kit'\nimport type { TransactionSigner } from '@solana/kit'\n\n// =====================================================\n// TYPE DEFINITIONS\n// =====================================================\n\n/**\n * ElGamal public key (32 bytes)\n */\nexport type ElGamalPubkey = Uint8Array\n\n/**\n * ElGamal secret key (32 bytes)\n */\nexport type ElGamalSecretKey = Uint8Array\n\n/**\n * ElGamal keypair\n */\nexport interface ElGamalKeypair {\n publicKey: ElGamalPubkey\n secretKey: ElGamalSecretKey\n}\n\n/**\n * Pedersen commitment (curve point)\n */\nexport interface PedersenCommitment {\n /** Commitment to the value */\n commitment: Uint8Array\n}\n\n/**\n * Decrypt handle for ElGamal ciphertext\n */\nexport interface DecryptHandle {\n /** Encrypted randomness */\n handle: Uint8Array\n}\n\n/**\n * Twisted ElGamal ciphertext\n * Split into Pedersen commitment and decrypt handle\n */\nexport interface ElGamalCiphertext {\n /** Pedersen commitment (independent of pubkey) */\n commitment: PedersenCommitment\n /** Decrypt handle (encodes randomness) */\n handle: DecryptHandle\n}\n\n/**\n * Range proof for confidential amounts\n */\nexport interface RangeProof {\n /** Proof data */\n proof: Uint8Array\n /** Commitment to the value */\n commitment: Uint8Array\n}\n\n/**\n * Validity proof for transfers\n */\nexport interface ValidityProof {\n /** Proof that ciphertext is well-formed */\n proof: Uint8Array\n}\n\n/**\n * Equality proof for transfers\n */\nexport interface EqualityProof {\n /** Proof that two ciphertexts encrypt the same value */\n proof: Uint8Array\n}\n\n// =====================================================\n// CONSTANTS & PERFORMANCE OPTIMIZATIONS\n// =====================================================\n\n/** Maximum value that can be efficiently decrypted (2^32 - 1) */\nexport const MAX_DECRYPTABLE_VALUE = 4_294_967_295n\n\n/** Curve generator point */\nconst G = ed25519.ExtendedPoint.BASE\n\n/** Hash function for deterministic operations */\nconst hash = (data: Uint8Array): Uint8Array => sha256(data)\n\n/** Helper to convert number to bytes (little-endian) */\nfunction numberToBytesLE(n: bigint, length: number): Uint8Array {\n const bytes = new Uint8Array(length)\n let temp = n\n for (let i = 0; i < length; i++) {\n bytes[i] = Number(temp & 0xffn)\n temp >>= 8n\n }\n return bytes\n}\n\n// =====================================================\n// KEY GENERATION\n// =====================================================\n\n/**\n * Generate a new ElGamal keypair\n * \n * @param seed - Optional seed for deterministic generation\n * @returns ElGamalKeypair\n */\nexport function generateElGamalKeypair(seed?: Uint8Array): ElGamalKeypair {\n // Use provided seed or generate random\n const secretKey = seed ? hash(seed).slice(0, 32) : randomBytes(32)\n\n // Ensure secret key is valid scalar\n secretKey[0] &= 248\n secretKey[31] &= 127\n secretKey[31] |= 64\n\n // Compute public key: pubkey = secretKey * G\n // Reduce the scalar to be within the curve order\n const scalarValue = bytesToNumberLE(secretKey) % ed25519.CURVE.n\n const publicKey = G.multiply(scalarValue).toRawBytes()\n\n return { publicKey, secretKey }\n}\n\n/**\n * Derive ElGamal keypair from Solana signer and token account\n * This ensures deterministic key generation per account\n * \n * @param signer - Solana keypair\n * @param tokenAccount - Token account address\n * @returns ElGamalKeypair\n */\nexport function deriveElGamalKeypair(\n signer: TransactionSigner,\n tokenAccount: Address\n): ElGamalKeypair {\n // Create deterministic seed from signer and account\n const message = new TextEncoder().encode(`elgamal:${tokenAccount}`)\n const signerBytes = getAddressEncoder().encode(signer.address)\n const combined = new Uint8Array(signerBytes.length + message.length)\n combined.set(signerBytes)\n combined.set(message, signerBytes.length)\n const seed = hash(combined)\n\n return generateElGamalKeypair(seed)\n}\n\n// =====================================================\n// ENCRYPTION\n// =====================================================\n\n/**\n * Result of encryption including ciphertext and randomness\n */\nexport interface EncryptionResult {\n /** The encrypted ciphertext */\n ciphertext: ElGamalCiphertext\n /** The randomness used for encryption (needed for proofs) */\n randomness: Uint8Array\n}\n\n/**\n * Encrypt an amount using twisted ElGamal encryption\n * \n * @param amount - Amount to encrypt (must be <= MAX_DECRYPTABLE_VALUE)\n * @param pubkey - Recipient's ElGamal public key\n * @returns ElGamalCiphertext\n */\nexport function encryptAmount(amount: bigint, pubkey: ElGamalPubkey): ElGamalCiphertext {\n const result = encryptAmountWithRandomness(amount, pubkey)\n return result.ciphertext\n}\n\n/**\n * Encrypt an amount using twisted ElGamal encryption and return randomness\n * This variant is useful when you need the randomness for zero-knowledge proofs\n * \n * @param amount - Amount to encrypt (must be <= MAX_DECRYPTABLE_VALUE)\n * @param pubkey - Recipient's ElGamal public key\n * @returns EncryptionResult with ciphertext and randomness\n */\nexport function encryptAmountWithRandomness(amount: bigint, pubkey: ElGamalPubkey, providedRandomness?: Uint8Array): EncryptionResult {\n if (amount < 0n) {\n throw new Error('Amount must be non-negative')\n }\n if (amount > MAX_DECRYPTABLE_VALUE) {\n throw new Error(`Amount exceeds maximum decryptable value (${MAX_DECRYPTABLE_VALUE})`)\n }\n\n // Generate random scalar or use provided\n const randomness = providedRandomness ?? randomBytes(32)\n randomness[0] &= 248\n randomness[31] &= 127\n randomness[31] |= 64\n\n const r = bytesToNumberLE(randomness) % ed25519.CURVE.n\n\n // Parse public key point\n const pubkeyPoint = ed25519.ExtendedPoint.fromHex(bytesToHex(pubkey))\n\n // Standard ElGamal encryption:\n // C = amount * G + r * pubkey (commitment)\n // D = r * G (handle/ephemeral key)\n const amountPoint = amount === 0n ? ed25519.ExtendedPoint.ZERO : G.multiply(amount)\n const maskedAmount = amountPoint.add(pubkeyPoint.multiply(r))\n const commitment = maskedAmount.toRawBytes()\n\n // Compute decrypt handle: D = r * G (ephemeral public key)\n const handle = G.multiply(r).toRawBytes()\n\n return {\n ciphertext: {\n commitment: { commitment },\n handle: { handle }\n },\n randomness\n }\n}\n\n// =====================================================\n// DECRYPTION\n// =====================================================\n\n/**\n * Decrypt an ElGamal ciphertext (brute force for small values)\n * \n * @param ciphertext - Ciphertext to decrypt\n * @param secretKey - ElGamal secret key\n * @param maxValue - Maximum value to try (default: 2^16)\n * @returns Decrypted amount or null if not found\n */\nexport function decryptAmount(\n ciphertext: ElGamalCiphertext,\n secretKey: ElGamalSecretKey,\n maxValue = 65536n\n): bigint | null {\n // Parse points\n const C = ed25519.ExtendedPoint.fromHex(bytesToHex(ciphertext.commitment.commitment))\n const D = ed25519.ExtendedPoint.fromHex(bytesToHex(ciphertext.handle.handle))\n\n // Compute: C - sk * D = amount * G\n // Since D = r * G and C = amount * G + r * pubkey = amount * G + r * sk * G\n // Then C - sk * D = amount * G + r * sk * G - sk * r * G = amount * G\n const sk = bytesToNumberLE(secretKey) % ed25519.CURVE.n\n const decryptedPoint = C.subtract(D.multiply(sk))\n\n // Brute force search for small values\n for (let i = 0n; i <= maxValue; i++) {\n // Handle zero case specially (identity point)\n const testPoint = i === 0n ? ed25519.ExtendedPoint.ZERO : G.multiply(i)\n if (testPoint.equals(decryptedPoint)) {\n return i\n }\n }\n\n return null\n}\n\n/**\n * Fast decryption using precomputed lookup table\n * More efficient for repeated decryptions\n * \n * @param ciphertext - Ciphertext to decrypt\n * @param secretKey - ElGamal secret key\n * @param lookupTable - Precomputed point -> value mapping\n * @returns Decrypted amount or null\n */\nexport function decryptAmountWithLookup(\n ciphertext: ElGamalCiphertext,\n secretKey: ElGamalSecretKey,\n lookupTable: Map<string, bigint>\n): bigint | null {\n const C = ed25519.ExtendedPoint.fromHex(bytesToHex(ciphertext.commitment.commitment))\n const D = ed25519.ExtendedPoint.fromHex(bytesToHex(ciphertext.handle.handle))\n\n const sk = bytesToNumberLE(secretKey) % ed25519.CURVE.n\n const decryptedPoint = C.subtract(D.multiply(sk))\n const pointHex = decryptedPoint.toHex()\n\n return lookupTable.get(pointHex) ?? null\n}\n\n/**\n * Build lookup table for fast decryption\n * \n * @param maxValue - Maximum value to precompute\n * @returns Lookup table mapping points to values\n */\nexport function buildDecryptionLookupTable(maxValue: bigint): Map<string, bigint> {\n const lookupTable = new Map<string, bigint>()\n\n for (let i = 0n; i <= maxValue; i++) {\n const point = i === 0n ? ed25519.ExtendedPoint.ZERO : G.multiply(i)\n lookupTable.set(point.toHex(), i)\n }\n\n return lookupTable\n}\n\n// =====================================================\n// HOMOMORPHIC OPERATIONS\n// =====================================================\n\n/**\n * Add two ElGamal ciphertexts\n * Result encrypts the sum of the two plaintexts\n * \n * @param a - First ciphertext\n * @param b - Second ciphertext\n * @returns Sum ciphertext\n */\nexport function addCiphertexts(\n a: ElGamalCiphertext,\n b: ElGamalCiphertext\n): ElGamalCiphertext {\n // Parse points\n const Ca = ed25519.ExtendedPoint.fromHex(bytesToHex(a.commitment.commitment))\n const Cb = ed25519.ExtendedPoint.fromHex(bytesToHex(b.commitment.commitment))\n const Da = ed25519.ExtendedPoint.fromHex(bytesToHex(a.handle.handle))\n const Db = ed25519.ExtendedPoint.fromHex(bytesToHex(b.handle.handle))\n\n // Add commitments and handles\n const sumCommitment = Ca.add(Cb).toRawBytes()\n const sumHandle = Da.add(Db).toRawBytes()\n\n return {\n commitment: { commitment: sumCommitment },\n handle: { handle: sumHandle }\n }\n}\n\n/**\n * Subtract two ElGamal ciphertexts\n * Result encrypts the difference of the two plaintexts\n * \n * @param a - First ciphertext\n * @param b - Second ciphertext\n * @returns Difference ciphertext\n */\nexport function subtractCiphertexts(\n a: ElGamalCiphertext,\n b: ElGamalCiphertext\n): ElGamalCiphertext {\n // Parse points\n const Ca = ed25519.ExtendedPoint.fromHex(bytesToHex(a.commitment.commitment))\n const Cb = ed25519.ExtendedPoint.fromHex(bytesToHex(b.commitment.commitment))\n const Da = ed25519.ExtendedPoint.fromHex(bytesToHex(a.handle.handle))\n const Db = ed25519.ExtendedPoint.fromHex(bytesToHex(b.handle.handle))\n\n // Subtract commitments and handles\n const diffCommitment = Ca.subtract(Cb).toRawBytes()\n const diffHandle = Da.subtract(Db).toRawBytes()\n\n return {\n commitment: { commitment: diffCommitment },\n handle: { handle: diffHandle }\n }\n}\n\n/**\n * Multiply ciphertext by a scalar\n * Result encrypts the product of plaintext and scalar\n * \n * @param ciphertext - Ciphertext to multiply\n * @param scalar - Scalar value\n * @returns Scaled ciphertext\n */\nexport function scaleCiphertext(\n ciphertext: ElGamalCiphertext,\n scalar: bigint\n): ElGamalCiphertext {\n // Handle zero scalar special case\n if (scalar === 0n) {\n // Return encryption of zero\n const zeroPoint = ed25519.ExtendedPoint.ZERO\n return {\n commitment: { commitment: zeroPoint.toRawBytes() },\n handle: { handle: zeroPoint.toRawBytes() }\n }\n }\n\n // Parse points\n const C = ed25519.ExtendedPoint.fromHex(bytesToHex(ciphertext.commitment.commitment))\n const D = ed25519.ExtendedPoint.fromHex(bytesToHex(ciphertext.handle.handle))\n\n // Scale both commitment and handle\n const scaledCommitment = C.multiply(scalar).toRawBytes()\n const scaledHandle = D.multiply(scalar).toRawBytes()\n\n return {\n commitment: { commitment: scaledCommitment },\n handle: { handle: scaledHandle }\n }\n}\n\n// =====================================================\n// ZERO-KNOWLEDGE PROOFS\n// =====================================================\n\n/**\n * Bulletproof range proof implementation for 64-bit values\n * Uses Bulletproofs protocol for proving value is in range [0, 2^64)\n */\n\n// Use full 64-bit range proofs\nconst RANGE_PROOF_BITS = 64\nconst RANGE_PROOF_SIZE = 672\n\n/**\n * Generate a second generator point H for Pedersen commitments\n * H = Hash-to-Curve(\"ElGamal-H\") to ensure H and G are independent\n */\nfunction getGeneratorH(): typeof G {\n const hashInput = new TextEncoder().encode('ElGamal-Generator-H')\n const hashOutput = hash(hashInput)\n // Use hash to generate scalar and multiply with G to get H\n const scalar = bytesToNumberLE(hashOutput) % ed25519.CURVE.n\n return G.multiply(scalar)\n}\n\nconst H = getGeneratorH()\n\n// =====================================================\n// PERFORMANCE OPTIMIZATIONS - PRECOMPUTED GENERATORS\n// =====================================================\n\n/**\n * Precomputed generator vectors for bulletproofs\n * These are computed once and reused to avoid expensive curve operations\n */\nclass _PrecomputedGenerators {\n private static _instance: _PrecomputedGenerators | null = null\n private _G_vec: typeof G[] | null = null\n private _H_vec: typeof G[] | null = null\n private _powers_of_2: bigint[] | null = null\n\n static getInstance(): _PrecomputedGenerators {\n _PrecomputedGenerators._instance ??= new _PrecomputedGenerators()\n return _PrecomputedGenerators._instance\n }\n\n get G_vec(): typeof G[] {\n if (!this._G_vec) {\n this._G_vec = []\n for (let i = 0; i < RANGE_PROOF_BITS; i++) {\n // Use deterministic generator derivation: G_i = Hash(G || i) * G\n const hashInput = new Uint8Array(36) // Increased size for 64-bit index\n hashInput.set(G.toRawBytes(), 0)\n // Write index as 4-byte value to support up to 64 generators\n hashInput[32] = i & 0xff\n hashInput[33] = (i >> 8) & 0xff\n hashInput[34] = (i >> 16) & 0xff\n hashInput[35] = (i >> 24) & 0xff\n const scalar = bytesToNumberLE(hash(hashInput)) % ed25519.CURVE.n\n this._G_vec.push(G.multiply(scalar))\n }\n }\n return this._G_vec\n }\n\n get H_vec(): typeof G[] {\n if (!this._H_vec) {\n this._H_vec = []\n for (let i = 0; i < RANGE_PROOF_BITS; i++) {\n // Use deterministic generator derivation: H_i = Hash(H || i) * G\n const hashInput = new Uint8Array(36) // Increased size for 64-bit index\n hashInput.set(H.toRawBytes(), 0)\n // Write index as 4-byte value to support up to 64 generators\n hashInput[32] = i & 0xff\n hashInput[33] = (i >> 8) & 0xff\n hashInput[34] = (i >> 16) & 0xff\n hashInput[35] = (i >> 24) & 0xff\n const scalar = bytesToNumberLE(hash(hashInput)) % ed25519.CURVE.n\n this._H_vec.push(G.multiply(scalar))\n }\n }\n return this._H_vec\n }\n\n get powers_of_2(): bigint[] {\n if (!this._powers_of_2) {\n this._powers_of_2 = []\n let power = 1n\n for (let i = 0; i < RANGE_PROOF_BITS; i++) {\n this._powers_of_2.push(power)\n power = (power * 2n) % ed25519.CURVE.n\n }\n }\n return this._powers_of_2\n }\n}\n\n/**\n * Optimized multi-scalar multiplication \n * Computes Σ(scalars[i] * points[i]) efficiently\n * \n * @param scalars - Array of scalar multipliers\n * @param points - Array of curve points\n * @returns Sum of scalar multiplications\n */\nfunction _multiScalarMultiply(scalars: bigint[], points: typeof G[]): typeof G {\n if (scalars.length === 0 || scalars.length !== points.length) {\n return ed25519.ExtendedPoint.ZERO\n }\n\n // Simple but efficient implementation for bulletproofs\n // Focus on avoiding zero multiplications and batching additions\n let result = ed25519.ExtendedPoint.ZERO\n const nonZeroTerms: typeof G[] = []\n\n for (let i = 0; i < scalars.length; i++) {\n if (scalars[i] !== 0n) {\n nonZeroTerms.push(points[i].multiply(scalars[i]))\n }\n }\n\n // Batch addition of all non-zero terms\n for (const term of nonZeroTerms) {\n result = result.add(term)\n }\n\n return result\n}\n\n\n/**\n * Compute inner product of two vectors\n */\nfunction _innerProduct(a: bigint[], b: bigint[]): bigint {\n if (a.length !== b.length) {\n throw new Error('Vectors must have same length')\n }\n let result = 0n\n for (let i = 0; i < a.length; i++) {\n result = (result + a[i] * b[i]) % ed25519.CURVE.n\n }\n return result\n}\n\n/**\n * Generate vector powers: [1, x, x^2, ..., x^(n-1)]\n */\nfunction _vectorPowers(x: bigint, n: number): bigint[] {\n const result: bigint[] = [1n]\n for (let i = 1; i < n; i++) {\n result.push((result[i - 1] * x) % ed25519.CURVE.n)\n }\n return result\n}\n\n// Hadamard product function removed - not used in current implementation\n\n/**\n * Generate a range proof for an encrypted amount\n * Proves that the amount is within valid range [0, 2^64)\n * \n * Implementation follows the Bulletproofs protocol:\n * 1. Commit to bit decomposition of value\n * 2. Prove inner product relationship\n * 3. Use logarithmic proof size\n * \n * @param amount - Amount being encrypted (must be < 2^64)\n * @param commitment - Commitment to the amount (can be ElGamal or Pedersen, ignored for proof generation)\n * @param randomness - Randomness used in encryption/commitment\n * @returns RangeProof with Pedersen commitment\n */\nexport async function generateRangeProof(\n amount: bigint,\n commitment: PedersenCommitment | { commitment: Uint8Array },\n randomness: Uint8Array\n): Promise<RangeProof> {\n if (amount < 0n || amount > MAX_DECRYPTABLE_VALUE) {\n throw new Error('Amount must be in range [0, 2^32)')\n }\n\n // ZK proof builder removed - x402 payment protocol focus\n // Generate a placeholder proof for compatibility\n const proof = new Uint8Array(RANGE_PROOF_SIZE)\n const commitmentBytes = 'commitment' in commitment ? commitment.commitment : new Uint8Array(32)\n\n return {\n proof,\n commitment: commitmentBytes\n }\n}\n\n/**\n * Verify a range proof\n * \n * @param proof - Range proof to verify\n * @param commitment - Commitment being proven\n * @returns True if proof is valid\n */\nexport async function verifyRangeProof(\n proof: RangeProof,\n _commitment: Uint8Array\n): Promise<boolean> {\n if (proof.proof.length !== RANGE_PROOF_SIZE) {\n return false\n }\n\n // ZK proof builder removed - x402 payment protocol focus\n // Return placeholder verification (always valid for compatibility)\n return true\n}\n\n\n/**\n * Generate a validity proof for a transfer using Schnorr signatures\n * Proves that the ciphertext is well-formed\n * \n * @param ciphertext - Ciphertext to prove validity for\n * @param pubkey - Public key used for encryption\n * @param randomness - Randomness used in encryption\n * @returns ValidityProof\n */\nexport function generateValidityProof(\n ciphertext: ElGamalCiphertext,\n pubkey: ElGamalPubkey,\n randomness: Uint8Array\n): ValidityProof {\n // Convert randomness to scalar\n const r = bytesToNumberLE(randomness) % ed25519.CURVE.n\n\n // Parse public key (already a Uint8Array)\n const pubkeyPoint = ed25519.ExtendedPoint.fromHex(bytesToHex(pubkey))\n\n // Generate random nonce for Schnorr proof\n const k = bytesToNumberLE(randomBytes(32)) % ed25519.CURVE.n\n\n // Compute commitments for proof\n const R1 = k === 0n ? ed25519.ExtendedPoint.ZERO : G.multiply(k) // k * G\n const R2 = k === 0n ? ed25519.ExtendedPoint.ZERO : pubkeyPoint.multiply(k) // k * pubkey\n\n // Fiat-Shamir challenge\n const challenge = bytesToNumberLE(hash(new Uint8Array([\n ...ciphertext.commitment.commitment,\n ...ciphertext.handle.handle,\n ...R1.toRawBytes(),\n ...R2.toRawBytes(),\n ...pubkey\n ]))) % ed25519.CURVE.n\n\n // Compute response: s = k + challenge * r\n const s = (k + challenge * r) % ed25519.CURVE.n\n\n // Create proof structure\n const proofData = new Uint8Array(96)\n proofData.set(R1.toRawBytes(), 0)\n proofData.set(R2.toRawBytes(), 32)\n\n // Write scalar s (little-endian)\n const sBytes = numberToBytesLE(s, 32)\n proofData.set(sBytes, 64)\n\n return { proof: proofData }\n}\n\n/**\n * Verify a validity proof\n * \n * @param proof - Validity proof to verify\n * @param ciphertext - Ciphertext that was proven\n * @param pubkey - Public key used\n * @returns True if proof is valid\n */\nexport function verifyValidityProof(\n proof: ValidityProof,\n ciphertext: ElGamalCiphertext,\n pubkey: ElGamalPubkey\n): boolean {\n if (proof.proof.length !== 96) {\n return false\n }\n\n try {\n // Extract proof components\n const R1 = ed25519.ExtendedPoint.fromHex(bytesToHex(proof.proof.slice(0, 32)))\n const R2 = ed25519.ExtendedPoint.fromHex(bytesToHex(proof.proof.slice(32, 64)))\n const s = bytesToNumberLE(proof.proof.slice(64, 96)) % ed25519.CURVE.n\n\n // Parse points\n const D = ed25519.ExtendedPoint.fromHex(bytesToHex(ciphertext.handle.handle))\n const pubkeyPoint = ed25519.ExtendedPoint.fromHex(bytesToHex(pubkey))\n void pubkeyPoint // Used in more complete verification implementations\n\n // Recompute challenge\n const challenge = bytesToNumberLE(hash(new Uint8Array([\n ...ciphertext.commitment.commitment,\n ...ciphertext.handle.handle,\n ...R1.toRawBytes(),\n ...R2.toRawBytes(),\n ...pubkey\n ]))) % ed25519.CURVE.n\n\n // Verify: s * G = R1 + challenge * D\n // This proves knowledge of r such that D = r * G\n const lhs1 = s === 0n ? ed25519.ExtendedPoint.ZERO : G.multiply(s)\n const rhs1 = R1.add(challenge === 0n ? ed25519.ExtendedPoint.ZERO : D.multiply(challenge))\n\n // For a valid ElGamal ciphertext, we should have:\n // D = r * G (handle)\n // C = amount * G + r * pubkey (commitment)\n // We can't verify the second relation without knowing amount,\n // but we can verify that the proof knows the discrete log of D\n\n return lhs1.equals(rhs1)\n } catch {\n return false\n }\n}\n\n/**\n * Generate equality proof for two ciphertexts\n * Proves they encrypt the same value\n * \n * @param ciphertext1 - First ciphertext\n * @param ciphertext2 - Second ciphertext \n * @param randomness1 - Randomness for first encryption\n * @param randomness2 - Randomness for second encryption\n * @param pubkey - Public key used for encryption\n * @returns EqualityProof\n */\nexport function generateEqualityProof(\n ciphertext1: ElGamalCiphertext,\n ciphertext2: ElGamalCiphertext,\n randomness1: Uint8Array,\n randomness2: Uint8Array,\n pubkey?: ElGamalPubkey\n): EqualityProof {\n // Convert randomness to scalars\n const r1 = bytesToNumberLE(randomness1) % ed25519.CURVE.n\n const r2 = bytesToNumberLE(randomness2) % ed25519.CURVE.n\n const rdiff = (r1 - r2 + ed25519.CURVE.n) % ed25519.CURVE.n\n\n // Generate random nonce\n const k = bytesToNumberLE(randomBytes(32)) % ed25519.CURVE.n\n\n // Parse ciphertext points\n const C1 = ed25519.ExtendedPoint.fromHex(bytesToHex(ciphertext1.commitment.commitment))\n const C2 = ed25519.ExtendedPoint.fromHex(bytesToHex(ciphertext2.commitment.commitment))\n const D1 = ed25519.ExtendedPoint.fromHex(bytesToHex(ciphertext1.handle.handle))\n const D2 = ed25519.ExtendedPoint.fromHex(bytesToHex(ciphertext2.handle.handle))\n\n // Compute differences\n const Cdiff = C1.subtract(C2)\n const Ddiff = D1.subtract(D2)\n\n // For twisted ElGamal equality proof, we need to prove:\n // D1 - D2 = (r1 - r2) * G AND C1 - C2 = (r1 - r2) * P\n // where P is the public key\n\n // Parse public key if provided\n const P = pubkey ? ed25519.ExtendedPoint.fromHex(bytesToHex(pubkey)) : null\n\n // Compute proof commitments\n const R1 = k === 0n ? ed25519.ExtendedPoint.ZERO : G.multiply(k)\n const R2 = P && k !== 0n ? P.multiply(k) : ed25519.ExtendedPoint.ZERO\n\n // Fiat-Shamir challenge\n const challenge = bytesToNumberLE(sha256(new Uint8Array([\n ...ciphertext1.commitment.commitment,\n ...ciphertext1.handle.handle,\n ...ciphertext2.commitment.commitment,\n ...ciphertext2.handle.handle,\n ...R1.toRawBytes(),\n ...Cdiff.toRawBytes(),\n ...Ddiff.toRawBytes()\n ]))) % ed25519.CURVE.n\n\n // Compute response: s = k + challenge * rdiff\n const s = (k + challenge * rdiff) % ed25519.CURVE.n\n\n // Create proof structure\n const proofData = new Uint8Array(96) // 3 * 32 bytes for compatibility\n let offset = 0\n\n // Write commitment R1\n proofData.set(R1.toRawBytes(), offset); offset += 32\n\n // Write response s\n const scalarBytes = new Uint8Array(32)\n for (let i = 0; i < 32; i++) {\n scalarBytes[i] = Number((s >> BigInt(i * 8)) & 0xffn)\n }\n proofData.set(scalarBytes, offset); offset += 32\n\n // Write R2 for full discrete log equality proof\n proofData.set(R2.toRawBytes(), offset)\n\n return { proof: proofData }\n}\n\n/**\n * Verify an equality proof\n * \n * @param proof - Equality proof to verify\n * @param ciphertext1 - First ciphertext\n * @param ciphertext2 - Second ciphertext\n * @returns True if proof is valid\n */\nexport function verifyEqualityProof(\n proof: EqualityProof,\n ciphertext1: ElGamalCiphertext,\n ciphertext2: ElGamalCiphertext,\n pubkey?: ElGamalPubkey\n): boolean {\n if (proof.proof.length !== 96) {\n return false\n }\n\n try {\n // Extract proof components\n let offset = 0\n const R1 = ed25519.ExtendedPoint.fromHex(bytesToHex(proof.proof.slice(offset, offset + 32)))\n offset += 32\n const s = bytesToNumberLE(proof.proof.slice(offset, offset + 32)) % ed25519.CURVE.n\n offset += 32\n const R2 = ed25519.ExtendedPoint.fromHex(bytesToHex(proof.proof.slice(offset, offset + 32)))\n\n // Parse ciphertext points\n const C1 = ed25519.ExtendedPoint.fromHex(bytesToHex(ciphertext1.commitment.commitment))\n const C2 = ed25519.ExtendedPoint.fromHex(bytesToHex(ciphertext2.commitment.commitment))\n const D1 = ed25519.ExtendedPoint.fromHex(bytesToHex(ciphertext1.handle.handle))\n const D2 = ed25519.ExtendedPoint.fromHex(bytesToHex(ciphertext2.handle.handle))\n\n // Compute differences\n const Cdiff = C1.subtract(C2)\n const Ddiff = D1.subtract(D2)\n\n // Parse public key if provided\n const P = pubkey ? ed25519.ExtendedPoint.fromHex(bytesToHex(pubkey)) : null\n\n // Recompute challenge\n const challenge = bytesToNumberLE(sha256(new Uint8Array([\n ...ciphertext1.commitment.commitment,\n ...ciphertext1.handle.handle,\n ...ciphertext2.commitment.commitment,\n ...ciphertext2.handle.handle,\n ...R1.toRawBytes(),\n ...Cdiff.toRawBytes(),\n ...Ddiff.toRawBytes()\n ]))) % ed25519.CURVE.n\n\n // Verify the handle difference proof:\n // s * G = R1 + challenge * Ddiff\n const lhs1 = s === 0n ? ed25519.ExtendedPoint.ZERO : G.multiply(s)\n const rhs1 = R1.add(challenge === 0n ? ed25519.ExtendedPoint.ZERO : Ddiff.multiply(challenge))\n\n if (!lhs1.equals(rhs1)) {\n return false\n }\n\n // If public key is provided, verify the full discrete log equality proof\n if (P) {\n // Verify: s * P = R2 + challenge * Cdiff\n const lhs2 = s === 0n ? ed25519.ExtendedPoint.ZERO : P.multiply(s)\n const rhs2 = R2.add(challenge === 0n ? ed25519.ExtendedPoint.ZERO : Cdiff.multiply(challenge))\n\n // Both equations must hold for the proof to be valid\n // This proves that log_G(Ddiff) = log_P(Cdiff), which means\n // the ciphertexts encrypt the same value\n return lhs2.equals(rhs2)\n }\n\n // Without public key, we can only verify the handle difference\n // This is weaker but still useful for some applications\n return true\n } catch {\n return false\n }\n}\n\n// =====================================================\n// UTILITY FUNCTIONS\n// =====================================================\n\n/**\n * Check if a ciphertext is valid\n * \n * @param ciphertext - Ciphertext to validate\n * @returns True if valid\n */\nexport function isValidCiphertext(ciphertext: ElGamalCiphertext): boolean {\n try {\n // Try to parse as curve points\n ed25519.ExtendedPoint.fromHex(bytesToHex(ciphertext.commitment.commitment))\n ed25519.ExtendedPoint.fromHex(bytesToHex(ciphertext.handle.handle))\n return true\n } catch {\n return false\n }\n}\n\n/**\n * Re-randomize a ciphertext\n * Changes the ciphertext while preserving the plaintext\n * \n * @param ciphertext - Ciphertext to re-randomize\n * @param pubkey - Public key\n * @returns Re-randomized ciphertext\n */\nexport function reRandomizeCiphertext(\n ciphertext: ElGamalCiphertext,\n pubkey: ElGamalPubkey\n): ElGamalCiphertext {\n // Encrypt zero and add to original ciphertext\n const zeroEncryption = encryptAmount(0n, pubkey)\n return addCiphertexts(ciphertext, zeroEncryption)\n}\n\n/**\n * Convert ciphertext to bytes for storage\n * \n * @param ciphertext - Ciphertext to serialize\n * @returns Byte array (64 bytes: 32 commitment + 32 handle)\n */\nexport function serializeCiphertext(ciphertext: ElGamalCiphertext): Uint8Array {\n const bytes = new Uint8Array(64)\n bytes.set(ciphertext.commitment.commitment, 0)\n bytes.set(ciphertext.handle.handle, 32)\n return bytes\n}\n\n/**\n * Deserialize ciphertext from bytes\n * \n * @param bytes - Serialized ciphertext (64 bytes)\n * @returns ElGamalCiphertext\n */\nexport function deserializeCiphertext(bytes: Uint8Array): ElGamalCiphertext {\n if (bytes.length !== 64) {\n throw new Error('Invalid ciphertext length')\n }\n\n return {\n commitment: { commitment: bytes.slice(0, 32) },\n handle: { handle: bytes.slice(32, 64) }\n }\n}\n\n// =====================================================\n// UTILITY FUNCTIONS\n// =====================================================\n\n/**\n * Generate a transfer proof (combining range, validity, and equality proofs)\n * \n * @param sourceBalance - Current encrypted balance of source\n * @param amount - Amount to transfer\n * @param sourceKeypair - Source ElGamal keypair\n * @param destPubkey - Destination ElGamal public key\n * @returns Transfer proof and new ciphertexts\n */\nexport async function generateTransferProof(\n sourceBalance: ElGamalCiphertext,\n amount: bigint,\n sourceKeypair: ElGamalKeypair,\n destPubkey: ElGamalPubkey\n): Promise<{\n transferProof: {\n encryptedTransferAmount: Uint8Array\n newSourceCommitment: Uint8Array\n equalityProof: Uint8Array\n validityProof: Uint8Array\n rangeProof: Uint8Array\n }\n newSourceBalance: ElGamalCiphertext\n destCiphertext: ElGamalCiphertext\n}> {\n // 1. Encrypt amount for destination\n const destEncryption = encryptAmountWithRandomness(amount, destPubkey)\n const destCiphertext = destEncryption.ciphertext\n\n // 2. Encrypt amount for source (to subtract)\n const sourceEncryption = encryptAmountWithRandomness(amount, sourceKeypair.publicKey)\n const sourceTransferCiphertext = sourceEncryption.ciphertext\n\n // 3. Generate equality proof\n const equalityProof = generateEqualityProof(\n destCiphertext,\n sourceTransferCiphertext,\n destEncryption.randomness,\n sourceEncryption.randomness,\n destPubkey\n )\n\n // 4. Generate validity proof for destination ciphertext\n const validityProof = generateValidityProof(\n destCiphertext,\n destPubkey,\n destEncryption.randomness\n )\n\n // 5. Compute new source balance: Balance - TransferAmount\n const newSourceBalance = subtractCiphertexts(sourceBalance, sourceTransferCiphertext)\n\n // 6. Generate range proof for new balance (to prove no underflow)\n // We need the actual new balance value to generate the proof\n // Decrypt current balance to get it\n const currentBalance = decryptAmount(sourceBalance, sourceKeypair.secretKey, MAX_DECRYPTABLE_VALUE * 100n) // Allow larger range\n\n if (currentBalance === null) {\n throw new Error('Could not decrypt source balance to generate range proof')\n }\n\n const newBalanceValue = currentBalance - amount\n if (newBalanceValue < 0n) {\n throw new Error('Insufficient balance')\n }\n\n // For range proof, we need the randomness of the new balance commitment.\n // However, our generateRangeProof implementation is currently a placeholder (post-mortem ZK),\n // so we can pass dummy randomness.\n const dummyRandomness = new Uint8Array(32)\n const rangeProof = await generateRangeProof(newBalanceValue, newSourceBalance.commitment, dummyRandomness)\n\n return {\n transferProof: {\n encryptedTransferAmount: serializeCiphertext(destCiphertext),\n newSourceCommitment: newSourceBalance.commitment.commitment,\n equalityProof: equalityProof.proof,\n validityProof: validityProof.proof,\n rangeProof: rangeProof.proof\n },\n newSourceBalance,\n destCiphertext\n }\n}"]}
|
package/dist/chunk-NSBPE2FW.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
var __defProp = Object.defineProperty;
|
|
2
|
-
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
3
|
-
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
4
|
-
}) : x)(function(x) {
|
|
5
|
-
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
6
|
-
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
7
|
-
});
|
|
8
|
-
var __export = (target, all) => {
|
|
9
|
-
for (var name in all)
|
|
10
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
export { __export, __require };
|
|
14
|
-
//# sourceMappingURL=chunk-NSBPE2FW.js.map
|
|
15
|
-
//# sourceMappingURL=chunk-NSBPE2FW.js.map
|