@auditable/privacy-pool-zk-sdk 0.0.2-rc.9 → 0.1.0
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/assets/main.wasm +0 -0
- package/assets/main_final.zkey +0 -0
- package/assets/witness_calculator.js +2 -0
- package/dist/cli.js +1500 -417
- package/dist/cli.js.map +1 -1
- package/dist/ephemeral-key.d.ts +28 -0
- package/dist/index.d.ts +12 -1
- package/dist/index.mjs +1238 -374
- package/dist/index.mjs.map +1 -1
- package/dist/sdk.d.ts +69 -8
- package/dist/shared-secret.d.ts +24 -0
- package/dist/stealth-address.d.ts +23 -0
- package/dist/stealth-sign-message.d.ts +7 -0
- package/dist/stealth-signature.d.ts +21 -0
- package/dist/types.d.ts +12 -1
- package/dist/withdrawal-transaction-input.d.ts +91 -0
- package/dist/witness.d.ts +2 -2
- package/package.json +10 -6
- package/pkg/client_sdk_wasm.d.ts +75 -32
- package/pkg/client_sdk_wasm.js +497 -360
- package/pkg/client_sdk_wasm_bg.wasm +0 -0
- package/pkg/client_sdk_wasm_bg.wasm.d.ts +12 -6
package/dist/cli.js
CHANGED
|
@@ -6,95 +6,1044 @@ var snarkjs = require('snarkjs');
|
|
|
6
6
|
|
|
7
7
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
8
8
|
function _interopNamespaceDefault(e) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
9
|
+
var n = Object.create(null);
|
|
10
|
+
if (e) {
|
|
11
|
+
Object.keys(e).forEach(function (k) {
|
|
12
|
+
if (k !== 'default') {
|
|
13
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
14
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
15
|
+
enumerable: true,
|
|
16
|
+
get: function () { return e[k]; }
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
n.default = e;
|
|
22
|
+
return Object.freeze(n);
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
var fs__namespace = /*#__PURE__*/_interopNamespaceDefault(fs);
|
|
26
26
|
var snarkjs__namespace = /*#__PURE__*/_interopNamespaceDefault(snarkjs);
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
function getDefaultExportFromCjs (x) {
|
|
29
|
+
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
|
|
30
|
+
}
|
|
29
31
|
|
|
30
|
-
|
|
32
|
+
var dist = {};
|
|
31
33
|
|
|
32
|
-
|
|
34
|
+
Object.defineProperty(dist, "__esModule", { value: true });
|
|
35
|
+
dist.bech32m = bech32 = dist.bech32 = void 0;
|
|
36
|
+
const ALPHABET = 'qpzry9x8gf2tvdw0s3jn54khce6mua7l';
|
|
37
|
+
const ALPHABET_MAP = {};
|
|
38
|
+
for (let z = 0; z < ALPHABET.length; z++) {
|
|
39
|
+
const x = ALPHABET.charAt(z);
|
|
40
|
+
ALPHABET_MAP[x] = z;
|
|
41
|
+
}
|
|
42
|
+
function polymodStep(pre) {
|
|
43
|
+
const b = pre >> 25;
|
|
44
|
+
return (((pre & 0x1ffffff) << 5) ^
|
|
45
|
+
(-((b >> 0) & 1) & 0x3b6a57b2) ^
|
|
46
|
+
(-((b >> 1) & 1) & 0x26508e6d) ^
|
|
47
|
+
(-((b >> 2) & 1) & 0x1ea119fa) ^
|
|
48
|
+
(-((b >> 3) & 1) & 0x3d4233dd) ^
|
|
49
|
+
(-((b >> 4) & 1) & 0x2a1462b3));
|
|
50
|
+
}
|
|
51
|
+
function prefixChk(prefix) {
|
|
52
|
+
let chk = 1;
|
|
53
|
+
for (let i = 0; i < prefix.length; ++i) {
|
|
54
|
+
const c = prefix.charCodeAt(i);
|
|
55
|
+
if (c < 33 || c > 126)
|
|
56
|
+
return 'Invalid prefix (' + prefix + ')';
|
|
57
|
+
chk = polymodStep(chk) ^ (c >> 5);
|
|
58
|
+
}
|
|
59
|
+
chk = polymodStep(chk);
|
|
60
|
+
for (let i = 0; i < prefix.length; ++i) {
|
|
61
|
+
const v = prefix.charCodeAt(i);
|
|
62
|
+
chk = polymodStep(chk) ^ (v & 0x1f);
|
|
63
|
+
}
|
|
64
|
+
return chk;
|
|
65
|
+
}
|
|
66
|
+
function convert(data, inBits, outBits, pad) {
|
|
67
|
+
let value = 0;
|
|
68
|
+
let bits = 0;
|
|
69
|
+
const maxV = (1 << outBits) - 1;
|
|
70
|
+
const result = [];
|
|
71
|
+
for (let i = 0; i < data.length; ++i) {
|
|
72
|
+
value = (value << inBits) | data[i];
|
|
73
|
+
bits += inBits;
|
|
74
|
+
while (bits >= outBits) {
|
|
75
|
+
bits -= outBits;
|
|
76
|
+
result.push((value >> bits) & maxV);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (pad) {
|
|
80
|
+
if (bits > 0) {
|
|
81
|
+
result.push((value << (outBits - bits)) & maxV);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
if (bits >= inBits)
|
|
86
|
+
return 'Excess padding';
|
|
87
|
+
if ((value << (outBits - bits)) & maxV)
|
|
88
|
+
return 'Non-zero padding';
|
|
89
|
+
}
|
|
90
|
+
return result;
|
|
91
|
+
}
|
|
92
|
+
function toWords(bytes) {
|
|
93
|
+
return convert(bytes, 8, 5, true);
|
|
94
|
+
}
|
|
95
|
+
function fromWordsUnsafe(words) {
|
|
96
|
+
const res = convert(words, 5, 8, false);
|
|
97
|
+
if (Array.isArray(res))
|
|
98
|
+
return res;
|
|
99
|
+
}
|
|
100
|
+
function fromWords(words) {
|
|
101
|
+
const res = convert(words, 5, 8, false);
|
|
102
|
+
if (Array.isArray(res))
|
|
103
|
+
return res;
|
|
104
|
+
throw new Error(res);
|
|
105
|
+
}
|
|
106
|
+
function getLibraryFromEncoding(encoding) {
|
|
107
|
+
let ENCODING_CONST;
|
|
108
|
+
if (encoding === 'bech32') {
|
|
109
|
+
ENCODING_CONST = 1;
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
ENCODING_CONST = 0x2bc830a3;
|
|
113
|
+
}
|
|
114
|
+
function encode(prefix, words, LIMIT) {
|
|
115
|
+
LIMIT = LIMIT || 90;
|
|
116
|
+
if (prefix.length + 7 + words.length > LIMIT)
|
|
117
|
+
throw new TypeError('Exceeds length limit');
|
|
118
|
+
prefix = prefix.toLowerCase();
|
|
119
|
+
// determine chk mod
|
|
120
|
+
let chk = prefixChk(prefix);
|
|
121
|
+
if (typeof chk === 'string')
|
|
122
|
+
throw new Error(chk);
|
|
123
|
+
let result = prefix + '1';
|
|
124
|
+
for (let i = 0; i < words.length; ++i) {
|
|
125
|
+
const x = words[i];
|
|
126
|
+
if (x >> 5 !== 0)
|
|
127
|
+
throw new Error('Non 5-bit word');
|
|
128
|
+
chk = polymodStep(chk) ^ x;
|
|
129
|
+
result += ALPHABET.charAt(x);
|
|
130
|
+
}
|
|
131
|
+
for (let i = 0; i < 6; ++i) {
|
|
132
|
+
chk = polymodStep(chk);
|
|
133
|
+
}
|
|
134
|
+
chk ^= ENCODING_CONST;
|
|
135
|
+
for (let i = 0; i < 6; ++i) {
|
|
136
|
+
const v = (chk >> ((5 - i) * 5)) & 0x1f;
|
|
137
|
+
result += ALPHABET.charAt(v);
|
|
138
|
+
}
|
|
139
|
+
return result;
|
|
140
|
+
}
|
|
141
|
+
function __decode(str, LIMIT) {
|
|
142
|
+
LIMIT = LIMIT || 90;
|
|
143
|
+
if (str.length < 8)
|
|
144
|
+
return str + ' too short';
|
|
145
|
+
if (str.length > LIMIT)
|
|
146
|
+
return 'Exceeds length limit';
|
|
147
|
+
// don't allow mixed case
|
|
148
|
+
const lowered = str.toLowerCase();
|
|
149
|
+
const uppered = str.toUpperCase();
|
|
150
|
+
if (str !== lowered && str !== uppered)
|
|
151
|
+
return 'Mixed-case string ' + str;
|
|
152
|
+
str = lowered;
|
|
153
|
+
const split = str.lastIndexOf('1');
|
|
154
|
+
if (split === -1)
|
|
155
|
+
return 'No separator character for ' + str;
|
|
156
|
+
if (split === 0)
|
|
157
|
+
return 'Missing prefix for ' + str;
|
|
158
|
+
const prefix = str.slice(0, split);
|
|
159
|
+
const wordChars = str.slice(split + 1);
|
|
160
|
+
if (wordChars.length < 6)
|
|
161
|
+
return 'Data too short';
|
|
162
|
+
let chk = prefixChk(prefix);
|
|
163
|
+
if (typeof chk === 'string')
|
|
164
|
+
return chk;
|
|
165
|
+
const words = [];
|
|
166
|
+
for (let i = 0; i < wordChars.length; ++i) {
|
|
167
|
+
const c = wordChars.charAt(i);
|
|
168
|
+
const v = ALPHABET_MAP[c];
|
|
169
|
+
if (v === undefined)
|
|
170
|
+
return 'Unknown character ' + c;
|
|
171
|
+
chk = polymodStep(chk) ^ v;
|
|
172
|
+
// not in the checksum?
|
|
173
|
+
if (i + 6 >= wordChars.length)
|
|
174
|
+
continue;
|
|
175
|
+
words.push(v);
|
|
176
|
+
}
|
|
177
|
+
if (chk !== ENCODING_CONST)
|
|
178
|
+
return 'Invalid checksum for ' + str;
|
|
179
|
+
return { prefix, words };
|
|
180
|
+
}
|
|
181
|
+
function decodeUnsafe(str, LIMIT) {
|
|
182
|
+
const res = __decode(str, LIMIT);
|
|
183
|
+
if (typeof res === 'object')
|
|
184
|
+
return res;
|
|
185
|
+
}
|
|
186
|
+
function decode(str, LIMIT) {
|
|
187
|
+
const res = __decode(str, LIMIT);
|
|
188
|
+
if (typeof res === 'object')
|
|
189
|
+
return res;
|
|
190
|
+
throw new Error(res);
|
|
191
|
+
}
|
|
192
|
+
return {
|
|
193
|
+
decodeUnsafe,
|
|
194
|
+
decode,
|
|
195
|
+
encode,
|
|
196
|
+
toWords,
|
|
197
|
+
fromWordsUnsafe,
|
|
198
|
+
fromWords,
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
var bech32 = dist.bech32 = getLibraryFromEncoding('bech32');
|
|
202
|
+
dist.bech32m = getLibraryFromEncoding('bech32m');
|
|
203
|
+
|
|
204
|
+
const STEALTH_ADDRESS_HRP = 'stpl1';
|
|
205
|
+
/** BIP-173 default 90 is too small for 64-byte payload (32+32 field coords) after 8→5 bit conversion. */
|
|
206
|
+
const BECH32_STEALTH_LIMIT = 1023;
|
|
207
|
+
function normalizeHex$2(hex) {
|
|
208
|
+
const s = hex.trim().replace(/^0x/i, '');
|
|
209
|
+
if (!/^[0-9a-fA-F]*$/.test(s)) {
|
|
210
|
+
throw new Error('stealth-address: hex must contain only 0-9, a-f');
|
|
211
|
+
}
|
|
212
|
+
return s.length % 2 === 0 ? s : `0${s}`;
|
|
213
|
+
}
|
|
214
|
+
function hexToBytes$2(hex) {
|
|
215
|
+
const norm = normalizeHex$2(hex);
|
|
216
|
+
const out = new Uint8Array(norm.length / 2);
|
|
217
|
+
for (let i = 0; i < out.length; i++) {
|
|
218
|
+
out[i] = parseInt(norm.slice(i * 2, i * 2 + 2), 16);
|
|
219
|
+
}
|
|
220
|
+
return out;
|
|
221
|
+
}
|
|
222
|
+
function bytesToHex$1(bytes) {
|
|
223
|
+
let s = '';
|
|
224
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
225
|
+
s += bytes[i].toString(16).padStart(2, '0');
|
|
226
|
+
}
|
|
227
|
+
return s;
|
|
228
|
+
}
|
|
229
|
+
function concatBytes(a, b) {
|
|
230
|
+
const out = new Uint8Array(a.length + b.length);
|
|
231
|
+
out.set(a, 0);
|
|
232
|
+
out.set(b, a.length);
|
|
233
|
+
return out;
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Encodes `x || y` as Bech32 (BIP-173) with human-readable part {@link STEALTH_ADDRESS_HRP} (`stpl1`).
|
|
237
|
+
* `x` and `y` must have the same byte length so decoding can split the payload in half.
|
|
238
|
+
*/
|
|
239
|
+
function encodeStealthAddress(decoded) {
|
|
240
|
+
const xb = hexToBytes$2(decoded.x);
|
|
241
|
+
const yb = hexToBytes$2(decoded.y);
|
|
242
|
+
if (xb.length !== yb.length) {
|
|
243
|
+
throw new Error('stealth-address: x and y must encode the same number of bytes for a reversible address');
|
|
244
|
+
}
|
|
245
|
+
const payload = concatBytes(xb, yb);
|
|
246
|
+
const words = bech32.toWords(payload);
|
|
247
|
+
return bech32.encode(STEALTH_ADDRESS_HRP, words, BECH32_STEALTH_LIMIT);
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Decodes a `stpl1` Bech32 stealth address into `x` and `y` (each half of the payload, as lowercase hex).
|
|
251
|
+
*/
|
|
252
|
+
function decodeStealthAddress(address) {
|
|
253
|
+
const { prefix, words } = bech32.decode(address, BECH32_STEALTH_LIMIT);
|
|
254
|
+
if (prefix !== STEALTH_ADDRESS_HRP) {
|
|
255
|
+
throw new Error(`stealth-address: expected HRP ${STEALTH_ADDRESS_HRP}, got ${JSON.stringify(prefix)}`);
|
|
256
|
+
}
|
|
257
|
+
const bytes = new Uint8Array(bech32.fromWords(words));
|
|
258
|
+
if (bytes.length === 0 || bytes.length % 2 !== 0) {
|
|
259
|
+
throw new Error('stealth-address: payload length must be positive and even');
|
|
260
|
+
}
|
|
261
|
+
const mid = bytes.length / 2;
|
|
262
|
+
return {
|
|
263
|
+
x: bytesToHex$1(bytes.subarray(0, mid)),
|
|
264
|
+
y: bytesToHex$1(bytes.subarray(mid)),
|
|
265
|
+
};
|
|
266
|
+
}
|
|
33
267
|
|
|
34
|
-
|
|
268
|
+
/** Default nonce when deriving the wallet sign-in message. */
|
|
269
|
+
const DEFAULT_STEALTH_SIGN_NONCE = 'main address';
|
|
270
|
+
/**
|
|
271
|
+
* Plaintext for Stellar wallet message signing (stealth address derivation).
|
|
272
|
+
* Sign the exact bytes of this string (UTF-8) with the stellar account key.
|
|
273
|
+
*/
|
|
274
|
+
function buildStealthAddressSignMessage(address, nonce = DEFAULT_STEALTH_SIGN_NONCE) {
|
|
275
|
+
return `Privacy layer app needs you to sign the message for stealth address derivation with address:\n${address}\n and nonce:\n${nonce}.\n\n This will not authorize any transaction.`;
|
|
276
|
+
}
|
|
35
277
|
|
|
36
|
-
|
|
278
|
+
/** Bech32 HRP for {@link DecodedEphemeralKey} only (`x ‖ y`, 64 bytes). */
|
|
279
|
+
const DECODED_EPHEMERAL_HRP = 'epk1';
|
|
280
|
+
/** Bech32 HRP for {@link DecodedDepositorSharedSecretPreimage} (96 bytes). */
|
|
281
|
+
const DEPOSITOR_SHARED_SECRET_PREIMAGE_HRP = 'epk_dep_pre1';
|
|
282
|
+
const FIELD_BYTES = 32;
|
|
283
|
+
const EPK_POINT_PAYLOAD = FIELD_BYTES * 2;
|
|
284
|
+
const EPK_DEP_PRE_PAYLOAD = FIELD_BYTES * 3;
|
|
285
|
+
const BECH32_LONG_LIMIT = 1023;
|
|
286
|
+
function normalizeHex$1(hex) {
|
|
287
|
+
const s = hex.trim().replace(/^0x/i, '');
|
|
288
|
+
if (!/^[0-9a-fA-F]*$/.test(s)) {
|
|
289
|
+
throw new Error('ephemeral-key: hex must contain only 0-9, a-f');
|
|
290
|
+
}
|
|
291
|
+
return s.length % 2 === 0 ? s : `0${s}`;
|
|
292
|
+
}
|
|
293
|
+
function hexToBytes$1(hex) {
|
|
294
|
+
const norm = normalizeHex$1(hex);
|
|
295
|
+
const out = new Uint8Array(norm.length / 2);
|
|
296
|
+
for (let i = 0; i < out.length; i++) {
|
|
297
|
+
out[i] = parseInt(norm.slice(i * 2, i * 2 + 2), 16);
|
|
298
|
+
}
|
|
299
|
+
return out;
|
|
300
|
+
}
|
|
301
|
+
function bytesToHex(bytes) {
|
|
302
|
+
let s = '';
|
|
303
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
304
|
+
s += bytes[i].toString(16).padStart(2, '0');
|
|
305
|
+
}
|
|
306
|
+
return s;
|
|
307
|
+
}
|
|
308
|
+
function concat2(a, b) {
|
|
309
|
+
const out = new Uint8Array(a.length + b.length);
|
|
310
|
+
out.set(a, 0);
|
|
311
|
+
out.set(b, a.length);
|
|
312
|
+
return out;
|
|
313
|
+
}
|
|
314
|
+
function concat3(a, b, c) {
|
|
315
|
+
const out = new Uint8Array(a.length + b.length + c.length);
|
|
316
|
+
out.set(a, 0);
|
|
317
|
+
out.set(b, a.length);
|
|
318
|
+
out.set(c, a.length + b.length);
|
|
319
|
+
return out;
|
|
320
|
+
}
|
|
321
|
+
function require32(label, bytes) {
|
|
322
|
+
if (bytes.length !== FIELD_BYTES) {
|
|
323
|
+
throw new Error(`ephemeral-key: ${label} must encode exactly ${FIELD_BYTES} bytes, got ${bytes.length}`);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* 32-byte big-endian integer as hex (64 chars), **< 2^253**, so BabyJub ECDH matches
|
|
328
|
+
* `circuits/encryption.circom` `Num2Bits(253)` and `libs/cryptography` `scalar_mul_253`.
|
|
329
|
+
*/
|
|
330
|
+
function generateRandomScalarHex32() {
|
|
331
|
+
const g = globalThis.crypto;
|
|
332
|
+
if (!g?.getRandomValues) {
|
|
333
|
+
throw new Error('ephemeral-key: crypto.getRandomValues is required');
|
|
334
|
+
}
|
|
335
|
+
const max = 1n << 253n;
|
|
336
|
+
for (let attempt = 0; attempt < 65536; attempt++) {
|
|
337
|
+
const b = new Uint8Array(32);
|
|
338
|
+
g.getRandomValues(b);
|
|
339
|
+
const hex = bytesToHex(b);
|
|
340
|
+
if (BigInt(`0x${hex}`) < max) {
|
|
341
|
+
return hex;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
throw new Error('ephemeral-key: failed to sample scalar < 2^253');
|
|
345
|
+
}
|
|
346
|
+
/** Bech32 `epk1`: encodes `x ‖ y` (64 bytes). */
|
|
347
|
+
function encodeDecodedEphemeralKey(decoded) {
|
|
348
|
+
const xb = hexToBytes$1(decoded.x);
|
|
349
|
+
const yb = hexToBytes$1(decoded.y);
|
|
350
|
+
require32('x', xb);
|
|
351
|
+
require32('y', yb);
|
|
352
|
+
const payload = concat2(xb, yb);
|
|
353
|
+
const words = bech32.toWords(payload);
|
|
354
|
+
return bech32.encode(DECODED_EPHEMERAL_HRP, words, BECH32_LONG_LIMIT);
|
|
355
|
+
}
|
|
356
|
+
function decodeDecodedEphemeralKey(encoded) {
|
|
357
|
+
const { prefix, words } = bech32.decode(encoded, BECH32_LONG_LIMIT);
|
|
358
|
+
if (prefix !== DECODED_EPHEMERAL_HRP) {
|
|
359
|
+
throw new Error(`ephemeral-key: expected HRP ${DECODED_EPHEMERAL_HRP}, got ${JSON.stringify(prefix)}`);
|
|
360
|
+
}
|
|
361
|
+
const bytes = new Uint8Array(bech32.fromWords(words));
|
|
362
|
+
if (bytes.length !== EPK_POINT_PAYLOAD) {
|
|
363
|
+
throw new Error(`ephemeral-key: epk1 payload must be ${EPK_POINT_PAYLOAD} bytes, got ${bytes.length}`);
|
|
364
|
+
}
|
|
365
|
+
return {
|
|
366
|
+
x: bytesToHex(bytes.subarray(0, FIELD_BYTES)),
|
|
367
|
+
y: bytesToHex(bytes.subarray(FIELD_BYTES)),
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
/** Bech32 `epk_dep_pre1`: `randomNonceScalar ‖ recipient.x ‖ recipient.y`. */
|
|
371
|
+
function encodeDepositorSharedSecretPreimage(decoded) {
|
|
372
|
+
const sb = hexToBytes$1(decoded.randomNonceScalar);
|
|
373
|
+
const xb = hexToBytes$1(decoded.recipientStealthAddress.x);
|
|
374
|
+
const yb = hexToBytes$1(decoded.recipientStealthAddress.y);
|
|
375
|
+
require32('randomNonceScalar', sb);
|
|
376
|
+
require32('recipientStealthAddress.x', xb);
|
|
377
|
+
require32('recipientStealthAddress.y', yb);
|
|
378
|
+
const payload = concat3(sb, xb, yb);
|
|
379
|
+
const words = bech32.toWords(payload);
|
|
380
|
+
return bech32.encode(DEPOSITOR_SHARED_SECRET_PREIMAGE_HRP, words, BECH32_LONG_LIMIT);
|
|
381
|
+
}
|
|
382
|
+
function decodeDepositorSharedSecretPreimage(encoded) {
|
|
383
|
+
const { prefix, words } = bech32.decode(encoded, BECH32_LONG_LIMIT);
|
|
384
|
+
if (prefix !== DEPOSITOR_SHARED_SECRET_PREIMAGE_HRP) {
|
|
385
|
+
throw new Error(`ephemeral-key: expected HRP ${DEPOSITOR_SHARED_SECRET_PREIMAGE_HRP}, got ${JSON.stringify(prefix)}`);
|
|
386
|
+
}
|
|
387
|
+
const bytes = new Uint8Array(bech32.fromWords(words));
|
|
388
|
+
if (bytes.length !== EPK_DEP_PRE_PAYLOAD) {
|
|
389
|
+
throw new Error(`ephemeral-key: epk_dep_pre1 payload must be ${EPK_DEP_PRE_PAYLOAD} bytes, got ${bytes.length}`);
|
|
390
|
+
}
|
|
391
|
+
return {
|
|
392
|
+
randomNonceScalar: bytesToHex(bytes.subarray(0, FIELD_BYTES)),
|
|
393
|
+
recipientStealthAddress: {
|
|
394
|
+
x: bytesToHex(bytes.subarray(FIELD_BYTES, FIELD_BYTES * 2)),
|
|
395
|
+
y: bytesToHex(bytes.subarray(FIELD_BYTES * 2)),
|
|
396
|
+
},
|
|
397
|
+
};
|
|
398
|
+
}
|
|
37
399
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
400
|
+
/** Matches `Transaction(20, 2, 2)` in `circuits/main.circom`. */
|
|
401
|
+
const TRANSACTION_TREE_DEPTH = 20;
|
|
402
|
+
/** BN254 scalar field modulus (ark `Fr`, circom signals). */
|
|
403
|
+
const BN254_SCALAR_MOD = 21888242871839275222246405745257275088548364400416034343698204186575808495617n;
|
|
404
|
+
/**
|
|
405
|
+
* BabyJub ECDH in `circuits/encryption.circom` uses `Num2Bits(253)`; scalars must be < 2^253
|
|
406
|
+
* (matches `libs/cryptography` `scalar_mul_253`).
|
|
407
|
+
*/
|
|
408
|
+
const BN254_BABYJUB_SCALAR_MAX_EXCLUSIVE = 1n << 253n;
|
|
409
|
+
function normalizeHex(hex) {
|
|
410
|
+
const s = hex.trim().replace(/^0x/i, '');
|
|
411
|
+
if (!/^[0-9a-fA-F]*$/.test(s)) {
|
|
412
|
+
throw new Error('withdrawal-transaction-input: invalid hex');
|
|
413
|
+
}
|
|
414
|
+
return s.length % 2 === 0 ? s : `0${s}`;
|
|
415
|
+
}
|
|
416
|
+
/** 32-byte field coordinate (hex, no 0x) → decimal string mod BN254 scalar field. */
|
|
417
|
+
function coordHexToDecimal(hex) {
|
|
418
|
+
const h = normalizeHex(hex);
|
|
419
|
+
if (h.length > 64) {
|
|
420
|
+
throw new Error('withdrawal-transaction-input: coordinate hex too long');
|
|
421
|
+
}
|
|
422
|
+
const v = BigInt(`0x${h}`);
|
|
423
|
+
return (v % BN254_SCALAR_MOD).toString(10);
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* 32-byte big-endian scalar hex → decimal for circom `ephemeralKeyScalar` / ECDH `priv`.
|
|
427
|
+
* Integer must be < 2^253 (not reduced mod r — values ≥ 2^253 are rejected).
|
|
428
|
+
*/
|
|
429
|
+
function scalarHexToFrDecimal(hex) {
|
|
430
|
+
const h = normalizeHex(hex);
|
|
431
|
+
if (h.length > 64) {
|
|
432
|
+
throw new Error('withdrawal-transaction-input: scalar hex too long');
|
|
433
|
+
}
|
|
434
|
+
const v = BigInt(`0x${h.padStart(64, '0').slice(-64)}`);
|
|
435
|
+
if (v >= BN254_BABYJUB_SCALAR_MAX_EXCLUSIVE) {
|
|
436
|
+
throw new Error('depositor ephemeral scalar must be < 2^253 (BabyJub Num2Bits); resample with random-scalar');
|
|
437
|
+
}
|
|
438
|
+
return v.toString(10);
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* Stellar G-address Ed25519 payload (32 bytes as 64 hex, optional 0x) → two circom public decimals
|
|
442
|
+
* (`withdrawAddressHi` / `withdrawAddressLo`). No mod-r; each half fits in 128 bits.
|
|
443
|
+
*/
|
|
444
|
+
function ed25519PubkeyPayloadHexToWithdrawFrDecimals(hex) {
|
|
445
|
+
const h = normalizeHex(hex).padStart(64, '0').slice(-64);
|
|
446
|
+
const hi = BigInt(`0x${h.slice(0, 32)}`);
|
|
447
|
+
const lo = BigInt(`0x${h.slice(32, 64)}`);
|
|
448
|
+
return { hi: hi.toString(10), lo: lo.toString(10) };
|
|
449
|
+
}
|
|
450
|
+
/** Uniform random `Fr` as decimal (32 random bytes, mod r). For Poseidon-only inputs (e.g. nullifiers). */
|
|
451
|
+
function randomFrDecimal() {
|
|
452
|
+
const hex = generateRandomScalarHex32();
|
|
453
|
+
const v = BigInt(`0x${normalizeHex(hex)}`);
|
|
454
|
+
return (v % BN254_SCALAR_MOD).toString(10);
|
|
455
|
+
}
|
|
456
|
+
/** Random scalar < 2^253 for BabyJub ECDH / `Num2Bits(253)` (uses {@link generateRandomScalarHex32}). */
|
|
457
|
+
function randomFrDecimal253() {
|
|
458
|
+
const hex = generateRandomScalarHex32();
|
|
459
|
+
return BigInt(`0x${normalizeHex(hex)}`).toString(10);
|
|
460
|
+
}
|
|
461
|
+
function zerosTreeSiblings() {
|
|
462
|
+
return Array(TRANSACTION_TREE_DEPTH).fill('0');
|
|
463
|
+
}
|
|
464
|
+
function dummyWithdraw(wasm) {
|
|
465
|
+
const nullifier = randomFrDecimal();
|
|
466
|
+
const secretHex = generateRandomScalarHex32();
|
|
467
|
+
const secret = (BigInt(`0x${normalizeHex(secretHex)}`) % BN254_SCALAR_MOD).toString(10);
|
|
468
|
+
const pt = wasm.ecdhEphemeralPublicKeyFromScalarHex(secretHex);
|
|
469
|
+
return {
|
|
470
|
+
value: '0',
|
|
471
|
+
nullifier,
|
|
472
|
+
secret,
|
|
473
|
+
ephemeralKeys: [coordHexToDecimal(pt.x), coordHexToDecimal(pt.y)],
|
|
474
|
+
stateSiblings: zerosTreeSiblings(),
|
|
475
|
+
stateIndex: '0',
|
|
476
|
+
};
|
|
477
|
+
}
|
|
478
|
+
function dummyDeposit(wasm) {
|
|
479
|
+
const nullifier = randomFrDecimal();
|
|
480
|
+
const ephemeralKeyScalar = randomFrDecimal253();
|
|
481
|
+
const skHex = generateRandomScalarHex32();
|
|
482
|
+
const pt = wasm.ecdhEphemeralPublicKeyFromScalarHex(skHex);
|
|
483
|
+
return {
|
|
484
|
+
value: '0',
|
|
485
|
+
nullifier,
|
|
486
|
+
ephemeralKeyScalar,
|
|
487
|
+
recipientPublicKeys: [coordHexToDecimal(pt.x), coordHexToDecimal(pt.y)],
|
|
488
|
+
};
|
|
489
|
+
}
|
|
490
|
+
function resolveWithdraw(slot, wasm) {
|
|
491
|
+
return slot === 'dummy' ? dummyWithdraw(wasm) : slot;
|
|
492
|
+
}
|
|
493
|
+
function resolveDeposit(slot, wasm) {
|
|
494
|
+
return slot === 'dummy' ? dummyDeposit(wasm) : slot;
|
|
495
|
+
}
|
|
496
|
+
function buildTransactionWitnessInput(publicParams, withdrawSlots, depositSlots, wasm) {
|
|
497
|
+
const w0 = resolveWithdraw(withdrawSlots[0], wasm);
|
|
498
|
+
const w1 = resolveWithdraw(withdrawSlots[1], wasm);
|
|
499
|
+
const d0 = resolveDeposit(depositSlots[0], wasm);
|
|
500
|
+
const d1 = resolveDeposit(depositSlots[1], wasm);
|
|
501
|
+
return {
|
|
502
|
+
stateRoot: publicParams.stateRoot,
|
|
503
|
+
withdrawAddressHi: publicParams.withdrawAddressHi,
|
|
504
|
+
withdrawAddressLo: publicParams.withdrawAddressLo,
|
|
505
|
+
privKeyScalar: publicParams.privKeyScalar,
|
|
506
|
+
withdrawnValues: [w0.value, w1.value],
|
|
507
|
+
withdrawnNullifiers: [w0.nullifier, w1.nullifier],
|
|
508
|
+
withdrawnSecrets: [w0.secret, w1.secret],
|
|
509
|
+
ephemeralKeys: [w0.ephemeralKeys, w1.ephemeralKeys],
|
|
510
|
+
stateSiblings: [w0.stateSiblings, w1.stateSiblings],
|
|
511
|
+
stateIndex: [w0.stateIndex, w1.stateIndex],
|
|
512
|
+
depositedValues: [d0.value, d1.value],
|
|
513
|
+
depositedNullifiers: [d0.nullifier, d1.nullifier],
|
|
514
|
+
depositedEphemeralKeyScalars: [d0.ephemeralKeyScalar, d1.ephemeralKeyScalar],
|
|
515
|
+
depositedRecipientPublicKeys: [d0.recipientPublicKeys, d1.recipientPublicKeys],
|
|
516
|
+
};
|
|
517
|
+
}
|
|
518
|
+
/** `stpl1…` stealth address → `[x, y]` as decimal field strings for `depositedRecipientPublicKeys`. */
|
|
519
|
+
function recipientPublicKeysDecimalFromStealthAddress(stealthAddress) {
|
|
520
|
+
const { x, y } = decodeStealthAddress(stealthAddress);
|
|
521
|
+
return [coordHexToDecimal(x), coordHexToDecimal(y)];
|
|
522
|
+
}
|
|
523
|
+
/** First withdraw leg: Merkle witness + depositor ECDH point coordinates (hex). */
|
|
524
|
+
function withdrawObjectFromMerkleWitness(witness, depositorEphemeralHex) {
|
|
525
|
+
return {
|
|
526
|
+
value: witness.value,
|
|
527
|
+
nullifier: witness.nullifier,
|
|
528
|
+
secret: witness.secret,
|
|
529
|
+
ephemeralKeys: [
|
|
530
|
+
coordHexToDecimal(depositorEphemeralHex.x),
|
|
531
|
+
coordHexToDecimal(depositorEphemeralHex.y),
|
|
532
|
+
],
|
|
533
|
+
stateSiblings: witness.stateSiblings,
|
|
534
|
+
stateIndex: witness.stateIndex,
|
|
535
|
+
};
|
|
536
|
+
}
|
|
42
537
|
|
|
43
|
-
|
|
44
|
-
|
|
538
|
+
function hexToBytes(hex) {
|
|
539
|
+
const out = new Uint8Array(hex.length / 2);
|
|
540
|
+
for (let i = 0; i < out.length; i++) {
|
|
541
|
+
out[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
|
|
542
|
+
}
|
|
543
|
+
return out;
|
|
544
|
+
}
|
|
545
|
+
function bytesToHexLower(bytes) {
|
|
546
|
+
let s = '';
|
|
547
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
548
|
+
s += bytes[i].toString(16).padStart(2, '0');
|
|
549
|
+
}
|
|
550
|
+
return s;
|
|
551
|
+
}
|
|
552
|
+
/** Base64 → bytes via `atob` (browsers; Node 16+). No Node `Buffer`. */
|
|
553
|
+
function decodeBase64ToBytes(s) {
|
|
554
|
+
const t = s.replace(/\s/g, '');
|
|
555
|
+
if (typeof atob !== 'function') {
|
|
556
|
+
throw new Error('Base64 decoding requires atob (browser or Node 16+)');
|
|
557
|
+
}
|
|
558
|
+
try {
|
|
559
|
+
const binary = atob(t);
|
|
560
|
+
const out = new Uint8Array(binary.length);
|
|
561
|
+
for (let i = 0; i < binary.length; i++) {
|
|
562
|
+
out[i] = binary.charCodeAt(i);
|
|
563
|
+
}
|
|
564
|
+
return out;
|
|
565
|
+
}
|
|
566
|
+
catch {
|
|
567
|
+
throw new Error('Invalid base64 signature');
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
/**
|
|
571
|
+
* Ed25519 signature as **128 hex chars** (optional `0x`) or **base64** (typically 88 chars for 64 bytes, whitespace ignored).
|
|
572
|
+
*/
|
|
573
|
+
function parseStellarEd25519SignatureRaw(input) {
|
|
574
|
+
const trimmed = input.trim();
|
|
575
|
+
const no0x = trimmed.replace(/^0x/i, '');
|
|
576
|
+
if (/^[0-9a-fA-F]+$/.test(no0x) && no0x.length === 128) {
|
|
577
|
+
return hexToBytes(no0x.toLowerCase());
|
|
578
|
+
}
|
|
579
|
+
const fromB64 = decodeBase64ToBytes(trimmed);
|
|
580
|
+
if (fromB64.length !== 64) {
|
|
581
|
+
throw new Error(`Decoded signature must be 64 bytes (Ed25519); got ${fromB64.length} from base64`);
|
|
582
|
+
}
|
|
583
|
+
return fromB64;
|
|
584
|
+
}
|
|
585
|
+
/** SHA-256 via Web Crypto only (`crypto.subtle`) — works in browsers and Node 19+ (global `crypto`). */
|
|
586
|
+
async function sha256(data) {
|
|
587
|
+
const subtle = globalThis.crypto?.subtle;
|
|
588
|
+
if (!subtle) {
|
|
589
|
+
throw new Error('SHA-256 requires crypto.subtle (HTTPS or localhost in browsers, or Node.js 19+).');
|
|
590
|
+
}
|
|
591
|
+
const copy = new Uint8Array(data.length);
|
|
592
|
+
copy.set(data);
|
|
593
|
+
return new Uint8Array(await subtle.digest('SHA-256', copy));
|
|
594
|
+
}
|
|
595
|
+
/**
|
|
596
|
+
* Stellar Ed25519 signature (hex or base64) → SHA-256(signature bytes) → scalar → WASM ECDH (no UTF-8 seed hash).
|
|
597
|
+
*/
|
|
598
|
+
async function stealthAddressFromStellarSignature(ecdhFromScalarHex, encodeStealth, signature) {
|
|
599
|
+
const raw = parseStellarEd25519SignatureRaw(signature);
|
|
600
|
+
const scalar = await sha256(raw);
|
|
601
|
+
const scalarHex = bytesToHexLower(scalar);
|
|
602
|
+
const decoded = ecdhFromScalarHex(scalarHex);
|
|
603
|
+
return encodeStealth(decoded);
|
|
604
|
+
}
|
|
605
|
+
/**
|
|
606
|
+
* SHA-256(signature) as 32-byte BE integer, truncated to **253 bits** (same effective scalar as
|
|
607
|
+
* `libs/cryptography` `scalar_mul_253` / circom `Num2Bits(253)`), decimal for `privKeyScalar`.
|
|
608
|
+
*/
|
|
609
|
+
async function privKeyScalarDecimalFromStellarSignature(signature) {
|
|
610
|
+
const raw = parseStellarEd25519SignatureRaw(signature);
|
|
611
|
+
const h = await sha256(raw);
|
|
612
|
+
let v = 0n;
|
|
613
|
+
for (let i = 0; i < h.length; i++) {
|
|
614
|
+
v = (v << 8n) + BigInt(h[i]);
|
|
615
|
+
}
|
|
616
|
+
const mask = BN254_BABYJUB_SCALAR_MAX_EXCLUSIVE - 1n;
|
|
617
|
+
return (v & mask).toString(10);
|
|
45
618
|
}
|
|
46
619
|
|
|
47
|
-
|
|
620
|
+
/* @ts-self-types="./client_sdk_wasm.d.ts" */
|
|
621
|
+
|
|
622
|
+
/**
|
|
623
|
+
* Merkle root, path, and coin field strings for the first withdraw leg (JSON → JSON).
|
|
624
|
+
* @param {string} coin_json
|
|
625
|
+
* @param {string} state_json
|
|
626
|
+
* @returns {string}
|
|
627
|
+
*/
|
|
628
|
+
function buildWithdrawMerkleWitness(coin_json, state_json) {
|
|
629
|
+
let deferred4_0;
|
|
630
|
+
let deferred4_1;
|
|
48
631
|
try {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
632
|
+
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
633
|
+
const ptr0 = passStringToWasm0(coin_json, wasm.__wbindgen_export, wasm.__wbindgen_export2);
|
|
634
|
+
const len0 = WASM_VECTOR_LEN;
|
|
635
|
+
const ptr1 = passStringToWasm0(state_json, wasm.__wbindgen_export, wasm.__wbindgen_export2);
|
|
636
|
+
const len1 = WASM_VECTOR_LEN;
|
|
637
|
+
wasm.buildWithdrawMerkleWitness(retptr, ptr0, len0, ptr1, len1);
|
|
638
|
+
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
639
|
+
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
640
|
+
var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
|
|
641
|
+
var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
|
|
642
|
+
var ptr3 = r0;
|
|
643
|
+
var len3 = r1;
|
|
644
|
+
if (r3) {
|
|
645
|
+
ptr3 = 0; len3 = 0;
|
|
646
|
+
throw takeObject(r2);
|
|
647
|
+
}
|
|
648
|
+
deferred4_0 = ptr3;
|
|
649
|
+
deferred4_1 = len3;
|
|
650
|
+
return getStringFromWasm0(ptr3, len3);
|
|
651
|
+
} finally {
|
|
652
|
+
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
653
|
+
wasm.__wbindgen_export4(deferred4_0, deferred4_1, 1);
|
|
52
654
|
}
|
|
53
655
|
}
|
|
54
656
|
|
|
55
|
-
|
|
657
|
+
/**
|
|
658
|
+
* Calculate nullifier hash from nullifier decimal string.
|
|
659
|
+
* Returns hex string (0x...)
|
|
660
|
+
* @param {string} nullifier_decimal
|
|
661
|
+
* @returns {string}
|
|
662
|
+
*/
|
|
663
|
+
function calculateNullifierHash(nullifier_decimal) {
|
|
664
|
+
let deferred3_0;
|
|
665
|
+
let deferred3_1;
|
|
666
|
+
try {
|
|
667
|
+
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
668
|
+
const ptr0 = passStringToWasm0(nullifier_decimal, wasm.__wbindgen_export, wasm.__wbindgen_export2);
|
|
669
|
+
const len0 = WASM_VECTOR_LEN;
|
|
670
|
+
wasm.calculateNullifierHash(retptr, ptr0, len0);
|
|
671
|
+
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
672
|
+
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
673
|
+
var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
|
|
674
|
+
var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
|
|
675
|
+
var ptr2 = r0;
|
|
676
|
+
var len2 = r1;
|
|
677
|
+
if (r3) {
|
|
678
|
+
ptr2 = 0; len2 = 0;
|
|
679
|
+
throw takeObject(r2);
|
|
680
|
+
}
|
|
681
|
+
deferred3_0 = ptr2;
|
|
682
|
+
deferred3_1 = len2;
|
|
683
|
+
return getStringFromWasm0(ptr2, len2);
|
|
684
|
+
} finally {
|
|
685
|
+
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
686
|
+
wasm.__wbindgen_export4(deferred3_0, deferred3_1, 1);
|
|
687
|
+
}
|
|
688
|
+
}
|
|
56
689
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
690
|
+
/**
|
|
691
|
+
* UTF-8 seed → `SHA256` → scalar → BabyJubJub `BASE8 * r` (circom `ECDHEphemeralKey`).
|
|
692
|
+
* `x` and `y` are lowercase hex (no `0x`). Bech32 / stealth string: TypeScript `encodeStealthAddress`.
|
|
693
|
+
* @param {string} seed
|
|
694
|
+
* @returns {any}
|
|
695
|
+
*/
|
|
696
|
+
function ecdhEphemeralPublicKey(seed) {
|
|
697
|
+
try {
|
|
698
|
+
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
699
|
+
const ptr0 = passStringToWasm0(seed, wasm.__wbindgen_export, wasm.__wbindgen_export2);
|
|
700
|
+
const len0 = WASM_VECTOR_LEN;
|
|
701
|
+
wasm.ecdhEphemeralPublicKey(retptr, ptr0, len0);
|
|
702
|
+
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
703
|
+
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
704
|
+
var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
|
|
705
|
+
if (r2) {
|
|
706
|
+
throw takeObject(r1);
|
|
707
|
+
}
|
|
708
|
+
return takeObject(r0);
|
|
709
|
+
} finally {
|
|
710
|
+
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
60
711
|
}
|
|
61
|
-
return cachedUint8ArrayMemory0;
|
|
62
712
|
}
|
|
63
713
|
|
|
64
|
-
|
|
714
|
+
/**
|
|
715
|
+
* 32-byte scalar as 64 hex chars (optional `0x`) → `ecdh_ephemeral_public_key` (no UTF-8 seed hash).
|
|
716
|
+
* @param {string} scalar_hex
|
|
717
|
+
* @returns {any}
|
|
718
|
+
*/
|
|
719
|
+
function ecdhEphemeralPublicKeyFromScalarHex(scalar_hex) {
|
|
720
|
+
try {
|
|
721
|
+
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
722
|
+
const ptr0 = passStringToWasm0(scalar_hex, wasm.__wbindgen_export, wasm.__wbindgen_export2);
|
|
723
|
+
const len0 = WASM_VECTOR_LEN;
|
|
724
|
+
wasm.ecdhEphemeralPublicKeyFromScalarHex(retptr, ptr0, len0);
|
|
725
|
+
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
726
|
+
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
727
|
+
var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
|
|
728
|
+
if (r2) {
|
|
729
|
+
throw takeObject(r1);
|
|
730
|
+
}
|
|
731
|
+
return takeObject(r0);
|
|
732
|
+
} finally {
|
|
733
|
+
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
734
|
+
}
|
|
735
|
+
}
|
|
65
736
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
737
|
+
/**
|
|
738
|
+
* Circuit `ECDH`: `priv * (pub_x, pub_y)` → shared key (`key[0], key[1]` hex).
|
|
739
|
+
* @param {string} priv_hex
|
|
740
|
+
* @param {string} pub_x_hex
|
|
741
|
+
* @param {string} pub_y_hex
|
|
742
|
+
* @returns {any}
|
|
743
|
+
*/
|
|
744
|
+
function ecdhSharedKey(priv_hex, pub_x_hex, pub_y_hex) {
|
|
745
|
+
try {
|
|
746
|
+
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
747
|
+
const ptr0 = passStringToWasm0(priv_hex, wasm.__wbindgen_export, wasm.__wbindgen_export2);
|
|
748
|
+
const len0 = WASM_VECTOR_LEN;
|
|
749
|
+
const ptr1 = passStringToWasm0(pub_x_hex, wasm.__wbindgen_export, wasm.__wbindgen_export2);
|
|
750
|
+
const len1 = WASM_VECTOR_LEN;
|
|
751
|
+
const ptr2 = passStringToWasm0(pub_y_hex, wasm.__wbindgen_export, wasm.__wbindgen_export2);
|
|
752
|
+
const len2 = WASM_VECTOR_LEN;
|
|
753
|
+
wasm.ecdhSharedKey(retptr, ptr0, len0, ptr1, len1, ptr2, len2);
|
|
754
|
+
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
755
|
+
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
756
|
+
var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
|
|
757
|
+
if (r2) {
|
|
758
|
+
throw takeObject(r1);
|
|
759
|
+
}
|
|
760
|
+
return takeObject(r0);
|
|
761
|
+
} finally {
|
|
762
|
+
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
75
763
|
}
|
|
76
|
-
return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
|
|
77
764
|
}
|
|
78
765
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
766
|
+
/**
|
|
767
|
+
* Generate a new coin with random nullifier, secret, and shared-secret field elements.
|
|
768
|
+
* `amount` is stroops (u64); JS passes `bigint`.
|
|
769
|
+
* Returns JSON: { coin: { value, nullifier, secret, commitment }, commitment_hex }
|
|
770
|
+
* @param {bigint} amount
|
|
771
|
+
* @returns {any}
|
|
772
|
+
*/
|
|
773
|
+
function generateCoin(amount) {
|
|
774
|
+
const ret = wasm.generateCoin(amount);
|
|
775
|
+
return takeObject(ret);
|
|
82
776
|
}
|
|
83
777
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
778
|
+
/**
|
|
779
|
+
* `Poseidon₁(scalar)` secret + fixed ECDH shared coords (hex), matching an aligned deposit witness.
|
|
780
|
+
* @param {string} scalar_hex
|
|
781
|
+
* @param {string} shared_x_hex
|
|
782
|
+
* @param {string} shared_y_hex
|
|
783
|
+
* @param {bigint} amount
|
|
784
|
+
* @returns {any}
|
|
785
|
+
*/
|
|
786
|
+
function generateCoinForDepositWithSharedHex(scalar_hex, shared_x_hex, shared_y_hex, amount) {
|
|
787
|
+
try {
|
|
788
|
+
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
789
|
+
const ptr0 = passStringToWasm0(scalar_hex, wasm.__wbindgen_export, wasm.__wbindgen_export2);
|
|
790
|
+
const len0 = WASM_VECTOR_LEN;
|
|
791
|
+
const ptr1 = passStringToWasm0(shared_x_hex, wasm.__wbindgen_export, wasm.__wbindgen_export2);
|
|
792
|
+
const len1 = WASM_VECTOR_LEN;
|
|
793
|
+
const ptr2 = passStringToWasm0(shared_y_hex, wasm.__wbindgen_export, wasm.__wbindgen_export2);
|
|
794
|
+
const len2 = WASM_VECTOR_LEN;
|
|
795
|
+
wasm.generateCoinForDepositWithSharedHex(retptr, ptr0, len0, ptr1, len1, ptr2, len2, amount);
|
|
796
|
+
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
797
|
+
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
798
|
+
var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
|
|
799
|
+
if (r2) {
|
|
800
|
+
throw takeObject(r1);
|
|
801
|
+
}
|
|
802
|
+
return takeObject(r0);
|
|
803
|
+
} finally {
|
|
804
|
+
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
805
|
+
}
|
|
88
806
|
}
|
|
89
807
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
808
|
+
/**
|
|
809
|
+
* `secret` in coin = `Poseidon255(1)(scalar)` per `deposit.circom`; scalar is 32-byte hex (64 chars, optional `0x`).
|
|
810
|
+
* @param {string} scalar_hex
|
|
811
|
+
* @param {bigint} amount
|
|
812
|
+
* @returns {any}
|
|
813
|
+
*/
|
|
814
|
+
function generateCoinFromDepositEphemeralScalarHex(scalar_hex, amount) {
|
|
815
|
+
try {
|
|
816
|
+
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
817
|
+
const ptr0 = passStringToWasm0(scalar_hex, wasm.__wbindgen_export, wasm.__wbindgen_export2);
|
|
818
|
+
const len0 = WASM_VECTOR_LEN;
|
|
819
|
+
wasm.generateCoinFromDepositEphemeralScalarHex(retptr, ptr0, len0, amount);
|
|
820
|
+
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
821
|
+
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
822
|
+
var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
|
|
823
|
+
if (r2) {
|
|
824
|
+
throw takeObject(r1);
|
|
825
|
+
}
|
|
826
|
+
return takeObject(r0);
|
|
827
|
+
} finally {
|
|
828
|
+
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
829
|
+
}
|
|
94
830
|
}
|
|
95
831
|
|
|
96
|
-
|
|
97
|
-
|
|
832
|
+
/**
|
|
833
|
+
* Same as `generateCoin`, but commitment uses the given ECDH shared key (64-char hex coords from `ecdhSharedKey`); shared coords are not stored in `coin` JSON.
|
|
834
|
+
* @param {string} shared_x_hex
|
|
835
|
+
* @param {string} shared_y_hex
|
|
836
|
+
* @param {bigint} amount
|
|
837
|
+
* @returns {any}
|
|
838
|
+
*/
|
|
839
|
+
function generateCoinWithSharedSecretHex(shared_x_hex, shared_y_hex, amount) {
|
|
840
|
+
try {
|
|
841
|
+
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
842
|
+
const ptr0 = passStringToWasm0(shared_x_hex, wasm.__wbindgen_export, wasm.__wbindgen_export2);
|
|
843
|
+
const len0 = WASM_VECTOR_LEN;
|
|
844
|
+
const ptr1 = passStringToWasm0(shared_y_hex, wasm.__wbindgen_export, wasm.__wbindgen_export2);
|
|
845
|
+
const len1 = WASM_VECTOR_LEN;
|
|
846
|
+
wasm.generateCoinWithSharedSecretHex(retptr, ptr0, len0, ptr1, len1, amount);
|
|
847
|
+
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
848
|
+
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
849
|
+
var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
|
|
850
|
+
if (r2) {
|
|
851
|
+
throw takeObject(r1);
|
|
852
|
+
}
|
|
853
|
+
return takeObject(r0);
|
|
854
|
+
} finally {
|
|
855
|
+
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
/**
|
|
860
|
+
* Convert snarkjs proof JSON to hex bytes for Soroban contract.
|
|
861
|
+
* @param {string} proof_json
|
|
862
|
+
* @returns {string}
|
|
863
|
+
*/
|
|
864
|
+
function proofToHex(proof_json) {
|
|
865
|
+
let deferred2_0;
|
|
866
|
+
let deferred2_1;
|
|
867
|
+
try {
|
|
868
|
+
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
869
|
+
const ptr0 = passStringToWasm0(proof_json, wasm.__wbindgen_export, wasm.__wbindgen_export2);
|
|
870
|
+
const len0 = WASM_VECTOR_LEN;
|
|
871
|
+
wasm.proofToHex(retptr, ptr0, len0);
|
|
872
|
+
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
873
|
+
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
874
|
+
deferred2_0 = r0;
|
|
875
|
+
deferred2_1 = r1;
|
|
876
|
+
return getStringFromWasm0(r0, r1);
|
|
877
|
+
} finally {
|
|
878
|
+
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
879
|
+
wasm.__wbindgen_export4(deferred2_0, deferred2_1, 1);
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
/**
|
|
884
|
+
* Convert snarkjs public signals JSON to hex bytes for Soroban contract.
|
|
885
|
+
* @param {string} public_json
|
|
886
|
+
* @returns {string}
|
|
887
|
+
*/
|
|
888
|
+
function publicToHex(public_json) {
|
|
889
|
+
let deferred2_0;
|
|
890
|
+
let deferred2_1;
|
|
891
|
+
try {
|
|
892
|
+
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
893
|
+
const ptr0 = passStringToWasm0(public_json, wasm.__wbindgen_export, wasm.__wbindgen_export2);
|
|
894
|
+
const len0 = WASM_VECTOR_LEN;
|
|
895
|
+
wasm.publicToHex(retptr, ptr0, len0);
|
|
896
|
+
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
897
|
+
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
898
|
+
deferred2_0 = r0;
|
|
899
|
+
deferred2_1 = r1;
|
|
900
|
+
return getStringFromWasm0(r0, r1);
|
|
901
|
+
} finally {
|
|
902
|
+
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
903
|
+
wasm.__wbindgen_export4(deferred2_0, deferred2_1, 1);
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
function __wbg_get_imports() {
|
|
908
|
+
const import0 = {
|
|
909
|
+
__proto__: null,
|
|
910
|
+
__wbg_String_8564e559799eccda: function(arg0, arg1) {
|
|
911
|
+
const ret = String(getObject(arg1));
|
|
912
|
+
const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);
|
|
913
|
+
const len1 = WASM_VECTOR_LEN;
|
|
914
|
+
getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
|
|
915
|
+
getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
|
|
916
|
+
},
|
|
917
|
+
__wbg___wbindgen_debug_string_5398f5bb970e0daa: function(arg0, arg1) {
|
|
918
|
+
const ret = debugString(getObject(arg1));
|
|
919
|
+
const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);
|
|
920
|
+
const len1 = WASM_VECTOR_LEN;
|
|
921
|
+
getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
|
|
922
|
+
getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
|
|
923
|
+
},
|
|
924
|
+
__wbg___wbindgen_is_function_3c846841762788c1: function(arg0) {
|
|
925
|
+
const ret = typeof(getObject(arg0)) === 'function';
|
|
926
|
+
return ret;
|
|
927
|
+
},
|
|
928
|
+
__wbg___wbindgen_is_object_781bc9f159099513: function(arg0) {
|
|
929
|
+
const val = getObject(arg0);
|
|
930
|
+
const ret = typeof(val) === 'object' && val !== null;
|
|
931
|
+
return ret;
|
|
932
|
+
},
|
|
933
|
+
__wbg___wbindgen_is_string_7ef6b97b02428fae: function(arg0) {
|
|
934
|
+
const ret = typeof(getObject(arg0)) === 'string';
|
|
935
|
+
return ret;
|
|
936
|
+
},
|
|
937
|
+
__wbg___wbindgen_is_undefined_52709e72fb9f179c: function(arg0) {
|
|
938
|
+
const ret = getObject(arg0) === undefined;
|
|
939
|
+
return ret;
|
|
940
|
+
},
|
|
941
|
+
__wbg___wbindgen_throw_6ddd609b62940d55: function(arg0, arg1) {
|
|
942
|
+
throw new Error(getStringFromWasm0(arg0, arg1));
|
|
943
|
+
},
|
|
944
|
+
__wbg_call_2d781c1f4d5c0ef8: function() { return handleError(function (arg0, arg1, arg2) {
|
|
945
|
+
const ret = getObject(arg0).call(getObject(arg1), getObject(arg2));
|
|
946
|
+
return addHeapObject(ret);
|
|
947
|
+
}, arguments); },
|
|
948
|
+
__wbg_crypto_38df2bab126b63dc: function(arg0) {
|
|
949
|
+
const ret = getObject(arg0).crypto;
|
|
950
|
+
return addHeapObject(ret);
|
|
951
|
+
},
|
|
952
|
+
__wbg_getRandomValues_c44a50d8cfdaebeb: function() { return handleError(function (arg0, arg1) {
|
|
953
|
+
getObject(arg0).getRandomValues(getObject(arg1));
|
|
954
|
+
}, arguments); },
|
|
955
|
+
__wbg_length_ea16607d7b61445b: function(arg0) {
|
|
956
|
+
const ret = getObject(arg0).length;
|
|
957
|
+
return ret;
|
|
958
|
+
},
|
|
959
|
+
__wbg_msCrypto_bd5a034af96bcba6: function(arg0) {
|
|
960
|
+
const ret = getObject(arg0).msCrypto;
|
|
961
|
+
return addHeapObject(ret);
|
|
962
|
+
},
|
|
963
|
+
__wbg_new_ab79df5bd7c26067: function() {
|
|
964
|
+
const ret = new Object();
|
|
965
|
+
return addHeapObject(ret);
|
|
966
|
+
},
|
|
967
|
+
__wbg_new_with_length_825018a1616e9e55: function(arg0) {
|
|
968
|
+
const ret = new Uint8Array(arg0 >>> 0);
|
|
969
|
+
return addHeapObject(ret);
|
|
970
|
+
},
|
|
971
|
+
__wbg_node_84ea875411254db1: function(arg0) {
|
|
972
|
+
const ret = getObject(arg0).node;
|
|
973
|
+
return addHeapObject(ret);
|
|
974
|
+
},
|
|
975
|
+
__wbg_process_44c7a14e11e9f69e: function(arg0) {
|
|
976
|
+
const ret = getObject(arg0).process;
|
|
977
|
+
return addHeapObject(ret);
|
|
978
|
+
},
|
|
979
|
+
__wbg_prototypesetcall_d62e5099504357e6: function(arg0, arg1, arg2) {
|
|
980
|
+
Uint8Array.prototype.set.call(getArrayU8FromWasm0(arg0, arg1), getObject(arg2));
|
|
981
|
+
},
|
|
982
|
+
__wbg_randomFillSync_6c25eac9869eb53c: function() { return handleError(function (arg0, arg1) {
|
|
983
|
+
getObject(arg0).randomFillSync(takeObject(arg1));
|
|
984
|
+
}, arguments); },
|
|
985
|
+
__wbg_require_b4edbdcf3e2a1ef0: function() { return handleError(function () {
|
|
986
|
+
const ret = module.require;
|
|
987
|
+
return addHeapObject(ret);
|
|
988
|
+
}, arguments); },
|
|
989
|
+
__wbg_set_6be42768c690e380: function(arg0, arg1, arg2) {
|
|
990
|
+
getObject(arg0)[takeObject(arg1)] = takeObject(arg2);
|
|
991
|
+
},
|
|
992
|
+
__wbg_static_accessor_GLOBAL_8adb955bd33fac2f: function() {
|
|
993
|
+
const ret = typeof global === 'undefined' ? null : global;
|
|
994
|
+
return isLikeNone(ret) ? 0 : addHeapObject(ret);
|
|
995
|
+
},
|
|
996
|
+
__wbg_static_accessor_GLOBAL_THIS_ad356e0db91c7913: function() {
|
|
997
|
+
const ret = typeof globalThis === 'undefined' ? null : globalThis;
|
|
998
|
+
return isLikeNone(ret) ? 0 : addHeapObject(ret);
|
|
999
|
+
},
|
|
1000
|
+
__wbg_static_accessor_SELF_f207c857566db248: function() {
|
|
1001
|
+
const ret = typeof self === 'undefined' ? null : self;
|
|
1002
|
+
return isLikeNone(ret) ? 0 : addHeapObject(ret);
|
|
1003
|
+
},
|
|
1004
|
+
__wbg_static_accessor_WINDOW_bb9f1ba69d61b386: function() {
|
|
1005
|
+
const ret = typeof window === 'undefined' ? null : window;
|
|
1006
|
+
return isLikeNone(ret) ? 0 : addHeapObject(ret);
|
|
1007
|
+
},
|
|
1008
|
+
__wbg_subarray_a068d24e39478a8a: function(arg0, arg1, arg2) {
|
|
1009
|
+
const ret = getObject(arg0).subarray(arg1 >>> 0, arg2 >>> 0);
|
|
1010
|
+
return addHeapObject(ret);
|
|
1011
|
+
},
|
|
1012
|
+
__wbg_versions_276b2795b1c6a219: function(arg0) {
|
|
1013
|
+
const ret = getObject(arg0).versions;
|
|
1014
|
+
return addHeapObject(ret);
|
|
1015
|
+
},
|
|
1016
|
+
__wbindgen_cast_0000000000000001: function(arg0, arg1) {
|
|
1017
|
+
// Cast intrinsic for `Ref(Slice(U8)) -> NamedExternref("Uint8Array")`.
|
|
1018
|
+
const ret = getArrayU8FromWasm0(arg0, arg1);
|
|
1019
|
+
return addHeapObject(ret);
|
|
1020
|
+
},
|
|
1021
|
+
__wbindgen_cast_0000000000000002: function(arg0, arg1) {
|
|
1022
|
+
// Cast intrinsic for `Ref(String) -> Externref`.
|
|
1023
|
+
const ret = getStringFromWasm0(arg0, arg1);
|
|
1024
|
+
return addHeapObject(ret);
|
|
1025
|
+
},
|
|
1026
|
+
__wbindgen_object_clone_ref: function(arg0) {
|
|
1027
|
+
const ret = getObject(arg0);
|
|
1028
|
+
return addHeapObject(ret);
|
|
1029
|
+
},
|
|
1030
|
+
__wbindgen_object_drop_ref: function(arg0) {
|
|
1031
|
+
takeObject(arg0);
|
|
1032
|
+
},
|
|
1033
|
+
};
|
|
1034
|
+
return {
|
|
1035
|
+
__proto__: null,
|
|
1036
|
+
"./client_sdk_wasm_bg.js": import0,
|
|
1037
|
+
};
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
function addHeapObject(obj) {
|
|
1041
|
+
if (heap_next === heap.length) heap.push(heap.length + 1);
|
|
1042
|
+
const idx = heap_next;
|
|
1043
|
+
heap_next = heap[idx];
|
|
1044
|
+
|
|
1045
|
+
heap[idx] = obj;
|
|
1046
|
+
return idx;
|
|
98
1047
|
}
|
|
99
1048
|
|
|
100
1049
|
function debugString(val) {
|
|
@@ -162,385 +1111,177 @@ function debugString(val) {
|
|
|
162
1111
|
return className;
|
|
163
1112
|
}
|
|
164
1113
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
const encodeString = (typeof cachedTextEncoder.encodeInto === 'function'
|
|
170
|
-
? function (arg, view) {
|
|
171
|
-
return cachedTextEncoder.encodeInto(arg, view);
|
|
1114
|
+
function dropObject(idx) {
|
|
1115
|
+
if (idx < 1028) return;
|
|
1116
|
+
heap[idx] = heap_next;
|
|
1117
|
+
heap_next = idx;
|
|
172
1118
|
}
|
|
173
|
-
: function (arg, view) {
|
|
174
|
-
const buf = cachedTextEncoder.encode(arg);
|
|
175
|
-
view.set(buf);
|
|
176
|
-
return {
|
|
177
|
-
read: arg.length,
|
|
178
|
-
written: buf.length
|
|
179
|
-
};
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
function passStringToWasm0(arg, malloc, realloc) {
|
|
183
|
-
|
|
184
|
-
if (realloc === undefined) {
|
|
185
|
-
const buf = cachedTextEncoder.encode(arg);
|
|
186
|
-
const ptr = malloc(buf.length, 1) >>> 0;
|
|
187
|
-
getUint8ArrayMemory0().subarray(ptr, ptr + buf.length).set(buf);
|
|
188
|
-
WASM_VECTOR_LEN = buf.length;
|
|
189
|
-
return ptr;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
let len = arg.length;
|
|
193
|
-
let ptr = malloc(len, 1) >>> 0;
|
|
194
|
-
|
|
195
|
-
const mem = getUint8ArrayMemory0();
|
|
196
|
-
|
|
197
|
-
let offset = 0;
|
|
198
|
-
|
|
199
|
-
for (; offset < len; offset++) {
|
|
200
|
-
const code = arg.charCodeAt(offset);
|
|
201
|
-
if (code > 0x7F) break;
|
|
202
|
-
mem[ptr + offset] = code;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
if (offset !== len) {
|
|
206
|
-
if (offset !== 0) {
|
|
207
|
-
arg = arg.slice(offset);
|
|
208
|
-
}
|
|
209
|
-
ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
|
|
210
|
-
const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len);
|
|
211
|
-
const ret = encodeString(arg, view);
|
|
212
|
-
|
|
213
|
-
offset += ret.written;
|
|
214
|
-
ptr = realloc(ptr, len, offset, 1) >>> 0;
|
|
215
|
-
}
|
|
216
1119
|
|
|
217
|
-
|
|
218
|
-
|
|
1120
|
+
function getArrayU8FromWasm0(ptr, len) {
|
|
1121
|
+
ptr = ptr >>> 0;
|
|
1122
|
+
return getUint8ArrayMemory0().subarray(ptr / 1, ptr / 1 + len);
|
|
219
1123
|
}
|
|
220
1124
|
|
|
221
1125
|
let cachedDataViewMemory0 = null;
|
|
222
|
-
|
|
223
1126
|
function getDataViewMemory0() {
|
|
224
1127
|
if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || (cachedDataViewMemory0.buffer.detached === undefined && cachedDataViewMemory0.buffer !== wasm.memory.buffer)) {
|
|
225
1128
|
cachedDataViewMemory0 = new DataView(wasm.memory.buffer);
|
|
226
1129
|
}
|
|
227
1130
|
return cachedDataViewMemory0;
|
|
228
1131
|
}
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
const ptr0 = passStringToWasm0(public_json, wasm.__wbindgen_export_1, wasm.__wbindgen_export_2);
|
|
240
|
-
const len0 = WASM_VECTOR_LEN;
|
|
241
|
-
wasm.publicToHex(retptr, ptr0, len0);
|
|
242
|
-
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
243
|
-
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
244
|
-
deferred2_0 = r0;
|
|
245
|
-
deferred2_1 = r1;
|
|
246
|
-
return getStringFromWasm0(r0, r1);
|
|
247
|
-
} finally {
|
|
248
|
-
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
249
|
-
wasm.__wbindgen_export_3(deferred2_0, deferred2_1, 1);
|
|
1132
|
+
|
|
1133
|
+
function getStringFromWasm0(ptr, len) {
|
|
1134
|
+
ptr = ptr >>> 0;
|
|
1135
|
+
return decodeText(ptr, len);
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
let cachedUint8ArrayMemory0 = null;
|
|
1139
|
+
function getUint8ArrayMemory0() {
|
|
1140
|
+
if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
|
|
1141
|
+
cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);
|
|
250
1142
|
}
|
|
1143
|
+
return cachedUint8ArrayMemory0;
|
|
251
1144
|
}
|
|
252
1145
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
* @param {string} nullifier_decimal
|
|
257
|
-
* @returns {string}
|
|
258
|
-
*/
|
|
259
|
-
function calculateNullifierHash(nullifier_decimal) {
|
|
260
|
-
let deferred3_0;
|
|
261
|
-
let deferred3_1;
|
|
1146
|
+
function getObject(idx) { return heap[idx]; }
|
|
1147
|
+
|
|
1148
|
+
function handleError(f, args) {
|
|
262
1149
|
try {
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
wasm.calculateNullifierHash(retptr, ptr0, len0);
|
|
267
|
-
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
268
|
-
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
269
|
-
var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
|
|
270
|
-
var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
|
|
271
|
-
var ptr2 = r0;
|
|
272
|
-
var len2 = r1;
|
|
273
|
-
if (r3) {
|
|
274
|
-
ptr2 = 0; len2 = 0;
|
|
275
|
-
throw takeObject(r2);
|
|
276
|
-
}
|
|
277
|
-
deferred3_0 = ptr2;
|
|
278
|
-
deferred3_1 = len2;
|
|
279
|
-
return getStringFromWasm0(ptr2, len2);
|
|
280
|
-
} finally {
|
|
281
|
-
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
282
|
-
wasm.__wbindgen_export_3(deferred3_0, deferred3_1, 1);
|
|
1150
|
+
return f.apply(this, args);
|
|
1151
|
+
} catch (e) {
|
|
1152
|
+
wasm.__wbindgen_export3(addHeapObject(e));
|
|
283
1153
|
}
|
|
284
1154
|
}
|
|
285
1155
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
const
|
|
298
|
-
const
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
1156
|
+
let heap = new Array(1024).fill(undefined);
|
|
1157
|
+
heap.push(undefined, null, true, false);
|
|
1158
|
+
|
|
1159
|
+
let heap_next = heap.length;
|
|
1160
|
+
|
|
1161
|
+
function isLikeNone(x) {
|
|
1162
|
+
return x === undefined || x === null;
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1165
|
+
function passStringToWasm0(arg, malloc, realloc) {
|
|
1166
|
+
if (realloc === undefined) {
|
|
1167
|
+
const buf = cachedTextEncoder.encode(arg);
|
|
1168
|
+
const ptr = malloc(buf.length, 1) >>> 0;
|
|
1169
|
+
getUint8ArrayMemory0().subarray(ptr, ptr + buf.length).set(buf);
|
|
1170
|
+
WASM_VECTOR_LEN = buf.length;
|
|
1171
|
+
return ptr;
|
|
1172
|
+
}
|
|
1173
|
+
|
|
1174
|
+
let len = arg.length;
|
|
1175
|
+
let ptr = malloc(len, 1) >>> 0;
|
|
1176
|
+
|
|
1177
|
+
const mem = getUint8ArrayMemory0();
|
|
1178
|
+
|
|
1179
|
+
let offset = 0;
|
|
1180
|
+
|
|
1181
|
+
for (; offset < len; offset++) {
|
|
1182
|
+
const code = arg.charCodeAt(offset);
|
|
1183
|
+
if (code > 0x7F) break;
|
|
1184
|
+
mem[ptr + offset] = code;
|
|
1185
|
+
}
|
|
1186
|
+
if (offset !== len) {
|
|
1187
|
+
if (offset !== 0) {
|
|
1188
|
+
arg = arg.slice(offset);
|
|
312
1189
|
}
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
1190
|
+
ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
|
|
1191
|
+
const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len);
|
|
1192
|
+
const ret = cachedTextEncoder.encodeInto(arg, view);
|
|
1193
|
+
|
|
1194
|
+
offset += ret.written;
|
|
1195
|
+
ptr = realloc(ptr, len, offset, 1) >>> 0;
|
|
319
1196
|
}
|
|
1197
|
+
|
|
1198
|
+
WASM_VECTOR_LEN = offset;
|
|
1199
|
+
return ptr;
|
|
320
1200
|
}
|
|
321
1201
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
*/
|
|
327
|
-
function generateCoin() {
|
|
328
|
-
const ret = wasm.generateCoin();
|
|
329
|
-
return takeObject(ret);
|
|
1202
|
+
function takeObject(idx) {
|
|
1203
|
+
const ret = getObject(idx);
|
|
1204
|
+
dropObject(idx);
|
|
1205
|
+
return ret;
|
|
330
1206
|
}
|
|
331
1207
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
const ptr0 = passStringToWasm0(proof_json, wasm.__wbindgen_export_1, wasm.__wbindgen_export_2);
|
|
343
|
-
const len0 = WASM_VECTOR_LEN;
|
|
344
|
-
wasm.proofToHex(retptr, ptr0, len0);
|
|
345
|
-
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
346
|
-
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
347
|
-
deferred2_0 = r0;
|
|
348
|
-
deferred2_1 = r1;
|
|
349
|
-
return getStringFromWasm0(r0, r1);
|
|
350
|
-
} finally {
|
|
351
|
-
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
352
|
-
wasm.__wbindgen_export_3(deferred2_0, deferred2_1, 1);
|
|
1208
|
+
let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
|
|
1209
|
+
cachedTextDecoder.decode();
|
|
1210
|
+
const MAX_SAFARI_DECODE_BYTES = 2146435072;
|
|
1211
|
+
let numBytesDecoded = 0;
|
|
1212
|
+
function decodeText(ptr, len) {
|
|
1213
|
+
numBytesDecoded += len;
|
|
1214
|
+
if (numBytesDecoded >= MAX_SAFARI_DECODE_BYTES) {
|
|
1215
|
+
cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
|
|
1216
|
+
cachedTextDecoder.decode();
|
|
1217
|
+
numBytesDecoded = len;
|
|
353
1218
|
}
|
|
1219
|
+
return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
const cachedTextEncoder = new TextEncoder();
|
|
1223
|
+
|
|
1224
|
+
if (!('encodeInto' in cachedTextEncoder)) {
|
|
1225
|
+
cachedTextEncoder.encodeInto = function (arg, view) {
|
|
1226
|
+
const buf = cachedTextEncoder.encode(arg);
|
|
1227
|
+
view.set(buf);
|
|
1228
|
+
return {
|
|
1229
|
+
read: arg.length,
|
|
1230
|
+
written: buf.length
|
|
1231
|
+
};
|
|
1232
|
+
};
|
|
354
1233
|
}
|
|
355
1234
|
|
|
356
|
-
|
|
1235
|
+
let WASM_VECTOR_LEN = 0;
|
|
1236
|
+
|
|
1237
|
+
let wasm;
|
|
1238
|
+
function __wbg_finalize_init(instance, module) {
|
|
1239
|
+
wasm = instance.exports;
|
|
1240
|
+
cachedDataViewMemory0 = null;
|
|
1241
|
+
cachedUint8ArrayMemory0 = null;
|
|
1242
|
+
return wasm;
|
|
1243
|
+
}
|
|
357
1244
|
|
|
358
1245
|
async function __wbg_load(module, imports) {
|
|
359
1246
|
if (typeof Response === 'function' && module instanceof Response) {
|
|
360
1247
|
if (typeof WebAssembly.instantiateStreaming === 'function') {
|
|
361
1248
|
try {
|
|
362
1249
|
return await WebAssembly.instantiateStreaming(module, imports);
|
|
363
|
-
|
|
364
1250
|
} catch (e) {
|
|
365
|
-
const validResponse = module.ok &&
|
|
1251
|
+
const validResponse = module.ok && expectedResponseType(module.type);
|
|
366
1252
|
|
|
367
1253
|
if (validResponse && module.headers.get('Content-Type') !== 'application/wasm') {
|
|
368
1254
|
console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);
|
|
369
1255
|
|
|
370
|
-
} else {
|
|
371
|
-
throw e;
|
|
372
|
-
}
|
|
1256
|
+
} else { throw e; }
|
|
373
1257
|
}
|
|
374
1258
|
}
|
|
375
1259
|
|
|
376
1260
|
const bytes = await module.arrayBuffer();
|
|
377
1261
|
return await WebAssembly.instantiate(bytes, imports);
|
|
378
|
-
|
|
379
1262
|
} else {
|
|
380
1263
|
const instance = await WebAssembly.instantiate(module, imports);
|
|
381
1264
|
|
|
382
1265
|
if (instance instanceof WebAssembly.Instance) {
|
|
383
1266
|
return { instance, module };
|
|
384
|
-
|
|
385
1267
|
} else {
|
|
386
1268
|
return instance;
|
|
387
1269
|
}
|
|
388
1270
|
}
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
function __wbg_get_imports() {
|
|
392
|
-
const imports = {};
|
|
393
|
-
imports.wbg = {};
|
|
394
|
-
imports.wbg.__wbg_buffer_a1a27a0dfa70165d = function(arg0) {
|
|
395
|
-
const ret = getObject(arg0).buffer;
|
|
396
|
-
return addHeapObject(ret);
|
|
397
|
-
};
|
|
398
|
-
imports.wbg.__wbg_call_f2db6205e5c51dc8 = function() { return handleError(function (arg0, arg1, arg2) {
|
|
399
|
-
const ret = getObject(arg0).call(getObject(arg1), getObject(arg2));
|
|
400
|
-
return addHeapObject(ret);
|
|
401
|
-
}, arguments) };
|
|
402
|
-
imports.wbg.__wbg_call_fbe8be8bf6436ce5 = function() { return handleError(function (arg0, arg1) {
|
|
403
|
-
const ret = getObject(arg0).call(getObject(arg1));
|
|
404
|
-
return addHeapObject(ret);
|
|
405
|
-
}, arguments) };
|
|
406
|
-
imports.wbg.__wbg_crypto_574e78ad8b13b65f = function(arg0) {
|
|
407
|
-
const ret = getObject(arg0).crypto;
|
|
408
|
-
return addHeapObject(ret);
|
|
409
|
-
};
|
|
410
|
-
imports.wbg.__wbg_getRandomValues_b8f5dbd5f3995a9e = function() { return handleError(function (arg0, arg1) {
|
|
411
|
-
getObject(arg0).getRandomValues(getObject(arg1));
|
|
412
|
-
}, arguments) };
|
|
413
|
-
imports.wbg.__wbg_msCrypto_a61aeb35a24c1329 = function(arg0) {
|
|
414
|
-
const ret = getObject(arg0).msCrypto;
|
|
415
|
-
return addHeapObject(ret);
|
|
416
|
-
};
|
|
417
|
-
imports.wbg.__wbg_new_07b483f72211fd66 = function() {
|
|
418
|
-
const ret = new Object();
|
|
419
|
-
return addHeapObject(ret);
|
|
420
|
-
};
|
|
421
|
-
imports.wbg.__wbg_new_e52b3efaaa774f96 = function(arg0) {
|
|
422
|
-
const ret = new Uint8Array(getObject(arg0));
|
|
423
|
-
return addHeapObject(ret);
|
|
424
|
-
};
|
|
425
|
-
imports.wbg.__wbg_newnoargs_ff528e72d35de39a = function(arg0, arg1) {
|
|
426
|
-
const ret = new Function(getStringFromWasm0(arg0, arg1));
|
|
427
|
-
return addHeapObject(ret);
|
|
428
|
-
};
|
|
429
|
-
imports.wbg.__wbg_newwithbyteoffsetandlength_3b01ecda099177e8 = function(arg0, arg1, arg2) {
|
|
430
|
-
const ret = new Uint8Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0);
|
|
431
|
-
return addHeapObject(ret);
|
|
432
|
-
};
|
|
433
|
-
imports.wbg.__wbg_newwithlength_08f872dc1e3ada2e = function(arg0) {
|
|
434
|
-
const ret = new Uint8Array(arg0 >>> 0);
|
|
435
|
-
return addHeapObject(ret);
|
|
436
|
-
};
|
|
437
|
-
imports.wbg.__wbg_node_905d3e251edff8a2 = function(arg0) {
|
|
438
|
-
const ret = getObject(arg0).node;
|
|
439
|
-
return addHeapObject(ret);
|
|
440
|
-
};
|
|
441
|
-
imports.wbg.__wbg_process_dc0fbacc7c1c06f7 = function(arg0) {
|
|
442
|
-
const ret = getObject(arg0).process;
|
|
443
|
-
return addHeapObject(ret);
|
|
444
|
-
};
|
|
445
|
-
imports.wbg.__wbg_randomFillSync_ac0988aba3254290 = function() { return handleError(function (arg0, arg1) {
|
|
446
|
-
getObject(arg0).randomFillSync(takeObject(arg1));
|
|
447
|
-
}, arguments) };
|
|
448
|
-
imports.wbg.__wbg_require_60cc747a6bc5215a = function() { return handleError(function () {
|
|
449
|
-
const ret = module.require;
|
|
450
|
-
return addHeapObject(ret);
|
|
451
|
-
}, arguments) };
|
|
452
|
-
imports.wbg.__wbg_set_3f1d0b984ed272ed = function(arg0, arg1, arg2) {
|
|
453
|
-
getObject(arg0)[takeObject(arg1)] = takeObject(arg2);
|
|
454
|
-
};
|
|
455
|
-
imports.wbg.__wbg_set_fe4e79d1ed3b0e9b = function(arg0, arg1, arg2) {
|
|
456
|
-
getObject(arg0).set(getObject(arg1), arg2 >>> 0);
|
|
457
|
-
};
|
|
458
|
-
imports.wbg.__wbg_static_accessor_GLOBAL_487c52c58d65314d = function() {
|
|
459
|
-
const ret = typeof global === 'undefined' ? null : global;
|
|
460
|
-
return isLikeNone(ret) ? 0 : addHeapObject(ret);
|
|
461
|
-
};
|
|
462
|
-
imports.wbg.__wbg_static_accessor_GLOBAL_THIS_ee9704f328b6b291 = function() {
|
|
463
|
-
const ret = typeof globalThis === 'undefined' ? null : globalThis;
|
|
464
|
-
return isLikeNone(ret) ? 0 : addHeapObject(ret);
|
|
465
|
-
};
|
|
466
|
-
imports.wbg.__wbg_static_accessor_SELF_78c9e3071b912620 = function() {
|
|
467
|
-
const ret = typeof self === 'undefined' ? null : self;
|
|
468
|
-
return isLikeNone(ret) ? 0 : addHeapObject(ret);
|
|
469
|
-
};
|
|
470
|
-
imports.wbg.__wbg_static_accessor_WINDOW_a093d21393777366 = function() {
|
|
471
|
-
const ret = typeof window === 'undefined' ? null : window;
|
|
472
|
-
return isLikeNone(ret) ? 0 : addHeapObject(ret);
|
|
473
|
-
};
|
|
474
|
-
imports.wbg.__wbg_subarray_dd4ade7d53bd8e26 = function(arg0, arg1, arg2) {
|
|
475
|
-
const ret = getObject(arg0).subarray(arg1 >>> 0, arg2 >>> 0);
|
|
476
|
-
return addHeapObject(ret);
|
|
477
|
-
};
|
|
478
|
-
imports.wbg.__wbg_versions_c01dfd4722a88165 = function(arg0) {
|
|
479
|
-
const ret = getObject(arg0).versions;
|
|
480
|
-
return addHeapObject(ret);
|
|
481
|
-
};
|
|
482
|
-
imports.wbg.__wbindgen_debug_string = function(arg0, arg1) {
|
|
483
|
-
const ret = debugString(getObject(arg1));
|
|
484
|
-
const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_export_1, wasm.__wbindgen_export_2);
|
|
485
|
-
const len1 = WASM_VECTOR_LEN;
|
|
486
|
-
getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
|
|
487
|
-
getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
|
|
488
|
-
};
|
|
489
|
-
imports.wbg.__wbindgen_is_function = function(arg0) {
|
|
490
|
-
const ret = typeof(getObject(arg0)) === 'function';
|
|
491
|
-
return ret;
|
|
492
|
-
};
|
|
493
|
-
imports.wbg.__wbindgen_is_object = function(arg0) {
|
|
494
|
-
const val = getObject(arg0);
|
|
495
|
-
const ret = typeof(val) === 'object' && val !== null;
|
|
496
|
-
return ret;
|
|
497
|
-
};
|
|
498
|
-
imports.wbg.__wbindgen_is_string = function(arg0) {
|
|
499
|
-
const ret = typeof(getObject(arg0)) === 'string';
|
|
500
|
-
return ret;
|
|
501
|
-
};
|
|
502
|
-
imports.wbg.__wbindgen_is_undefined = function(arg0) {
|
|
503
|
-
const ret = getObject(arg0) === undefined;
|
|
504
|
-
return ret;
|
|
505
|
-
};
|
|
506
|
-
imports.wbg.__wbindgen_memory = function() {
|
|
507
|
-
const ret = wasm.memory;
|
|
508
|
-
return addHeapObject(ret);
|
|
509
|
-
};
|
|
510
|
-
imports.wbg.__wbindgen_object_clone_ref = function(arg0) {
|
|
511
|
-
const ret = getObject(arg0);
|
|
512
|
-
return addHeapObject(ret);
|
|
513
|
-
};
|
|
514
|
-
imports.wbg.__wbindgen_object_drop_ref = function(arg0) {
|
|
515
|
-
takeObject(arg0);
|
|
516
|
-
};
|
|
517
|
-
imports.wbg.__wbindgen_string_new = function(arg0, arg1) {
|
|
518
|
-
const ret = getStringFromWasm0(arg0, arg1);
|
|
519
|
-
return addHeapObject(ret);
|
|
520
|
-
};
|
|
521
|
-
imports.wbg.__wbindgen_throw = function(arg0, arg1) {
|
|
522
|
-
throw new Error(getStringFromWasm0(arg0, arg1));
|
|
523
|
-
};
|
|
524
|
-
|
|
525
|
-
return imports;
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
function __wbg_finalize_init(instance, module) {
|
|
529
|
-
wasm = instance.exports;
|
|
530
|
-
__wbg_init.__wbindgen_wasm_module = module;
|
|
531
|
-
cachedDataViewMemory0 = null;
|
|
532
|
-
cachedUint8ArrayMemory0 = null;
|
|
533
|
-
|
|
534
1271
|
|
|
535
|
-
|
|
536
|
-
|
|
1272
|
+
function expectedResponseType(type) {
|
|
1273
|
+
switch (type) {
|
|
1274
|
+
case 'basic': case 'cors': case 'default': return true;
|
|
1275
|
+
}
|
|
1276
|
+
return false;
|
|
1277
|
+
}
|
|
537
1278
|
}
|
|
538
1279
|
|
|
539
1280
|
function initSync(module) {
|
|
540
1281
|
if (wasm !== undefined) return wasm;
|
|
541
1282
|
|
|
542
1283
|
|
|
543
|
-
if (
|
|
1284
|
+
if (module !== undefined) {
|
|
544
1285
|
if (Object.getPrototypeOf(module) === Object.prototype) {
|
|
545
1286
|
({module} = module);
|
|
546
1287
|
} else {
|
|
@@ -549,21 +1290,18 @@ function initSync(module) {
|
|
|
549
1290
|
}
|
|
550
1291
|
|
|
551
1292
|
const imports = __wbg_get_imports();
|
|
552
|
-
|
|
553
1293
|
if (!(module instanceof WebAssembly.Module)) {
|
|
554
1294
|
module = new WebAssembly.Module(module);
|
|
555
1295
|
}
|
|
556
|
-
|
|
557
1296
|
const instance = new WebAssembly.Instance(module, imports);
|
|
558
|
-
|
|
559
|
-
return __wbg_finalize_init(instance, module);
|
|
1297
|
+
return __wbg_finalize_init(instance);
|
|
560
1298
|
}
|
|
561
1299
|
|
|
562
1300
|
async function __wbg_init(module_or_path) {
|
|
563
1301
|
if (wasm !== undefined) return wasm;
|
|
564
1302
|
|
|
565
1303
|
|
|
566
|
-
if (
|
|
1304
|
+
if (module_or_path !== undefined) {
|
|
567
1305
|
if (Object.getPrototypeOf(module_or_path) === Object.prototype) {
|
|
568
1306
|
({module_or_path} = module_or_path);
|
|
569
1307
|
} else {
|
|
@@ -571,7 +1309,7 @@ async function __wbg_init(module_or_path) {
|
|
|
571
1309
|
}
|
|
572
1310
|
}
|
|
573
1311
|
|
|
574
|
-
if (
|
|
1312
|
+
if (module_or_path === undefined) {
|
|
575
1313
|
module_or_path = new URL('client_sdk_wasm_bg.wasm', (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli.js', document.baseURI).href)));
|
|
576
1314
|
}
|
|
577
1315
|
const imports = __wbg_get_imports();
|
|
@@ -582,18 +1320,24 @@ async function __wbg_init(module_or_path) {
|
|
|
582
1320
|
|
|
583
1321
|
const { instance, module } = await __wbg_load(await module_or_path, imports);
|
|
584
1322
|
|
|
585
|
-
return __wbg_finalize_init(instance
|
|
1323
|
+
return __wbg_finalize_init(instance);
|
|
586
1324
|
}
|
|
587
1325
|
|
|
588
1326
|
var wasmBindings = /*#__PURE__*/Object.freeze({
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
1327
|
+
__proto__: null,
|
|
1328
|
+
buildWithdrawMerkleWitness: buildWithdrawMerkleWitness,
|
|
1329
|
+
calculateNullifierHash: calculateNullifierHash,
|
|
1330
|
+
default: __wbg_init,
|
|
1331
|
+
ecdhEphemeralPublicKey: ecdhEphemeralPublicKey,
|
|
1332
|
+
ecdhEphemeralPublicKeyFromScalarHex: ecdhEphemeralPublicKeyFromScalarHex,
|
|
1333
|
+
ecdhSharedKey: ecdhSharedKey,
|
|
1334
|
+
generateCoin: generateCoin,
|
|
1335
|
+
generateCoinForDepositWithSharedHex: generateCoinForDepositWithSharedHex,
|
|
1336
|
+
generateCoinFromDepositEphemeralScalarHex: generateCoinFromDepositEphemeralScalarHex,
|
|
1337
|
+
generateCoinWithSharedSecretHex: generateCoinWithSharedSecretHex,
|
|
1338
|
+
initSync: initSync,
|
|
1339
|
+
proofToHex: proofToHex,
|
|
1340
|
+
publicToHex: publicToHex
|
|
597
1341
|
});
|
|
598
1342
|
|
|
599
1343
|
const isNode$2 = typeof process !== 'undefined' && !!process.versions?.node;
|
|
@@ -603,7 +1347,7 @@ async function loadWasm(wasmBinary) {
|
|
|
603
1347
|
return wasmModule;
|
|
604
1348
|
if (isNode$2) {
|
|
605
1349
|
if (wasmBinary) {
|
|
606
|
-
initSync(wasmBinary);
|
|
1350
|
+
initSync({ module: wasmBinary });
|
|
607
1351
|
}
|
|
608
1352
|
else {
|
|
609
1353
|
const path = await import('path');
|
|
@@ -612,13 +1356,13 @@ async function loadWasm(wasmBinary) {
|
|
|
612
1356
|
const dir = path.dirname(fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli.js', document.baseURI).href))));
|
|
613
1357
|
const wasmPath = path.resolve(dir, '..', 'pkg', 'client_sdk_wasm_bg.wasm');
|
|
614
1358
|
const buffer = fs.readFileSync(wasmPath);
|
|
615
|
-
initSync(buffer);
|
|
1359
|
+
initSync({ module: buffer });
|
|
616
1360
|
}
|
|
617
1361
|
wasmModule = wasmBindings;
|
|
618
1362
|
}
|
|
619
1363
|
else {
|
|
620
1364
|
if (wasmBinary) {
|
|
621
|
-
initSync(wasmBinary);
|
|
1365
|
+
initSync({ module: wasmBinary });
|
|
622
1366
|
}
|
|
623
1367
|
else {
|
|
624
1368
|
await __wbg_init();
|
|
@@ -628,10 +1372,6 @@ async function loadWasm(wasmBinary) {
|
|
|
628
1372
|
return wasmModule;
|
|
629
1373
|
}
|
|
630
1374
|
|
|
631
|
-
function getDefaultExportFromCjs (x) {
|
|
632
|
-
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
|
|
633
|
-
}
|
|
634
|
-
|
|
635
1375
|
var witness_calculator = async function builder(code, options) {
|
|
636
1376
|
|
|
637
1377
|
options = options || {};
|
|
@@ -666,6 +1406,8 @@ var witness_calculator = async function builder(code, options) {
|
|
|
666
1406
|
err = "Not enough memory.\n";
|
|
667
1407
|
} else if (code == 6) {
|
|
668
1408
|
err = "Input signal array access exceeds the size.\n";
|
|
1409
|
+
} else if (code == 7) {
|
|
1410
|
+
err = "Out of bounds array access.\n";
|
|
669
1411
|
} else {
|
|
670
1412
|
err = "Unknown error.\n";
|
|
671
1413
|
}
|
|
@@ -1090,6 +1832,29 @@ async function generateProof(wtns, zkey) {
|
|
|
1090
1832
|
return { proof, publicSignals };
|
|
1091
1833
|
}
|
|
1092
1834
|
|
|
1835
|
+
/**
|
|
1836
|
+
* Depositor: `randomNonceScalar * recipientStealthPoint` (same as circom `ECDH` with depositor scalar).
|
|
1837
|
+
*/
|
|
1838
|
+
function sharedSecretFromDepositorPreimage(ecdhShared, preimage) {
|
|
1839
|
+
const out = ecdhShared(preimage.randomNonceScalar, preimage.recipientStealthAddress.x, preimage.recipientStealthAddress.y);
|
|
1840
|
+
return { x: out.x, y: out.y };
|
|
1841
|
+
}
|
|
1842
|
+
/**
|
|
1843
|
+
* Recipient: `recipientScalar * ephemeralKey` (same shared point as depositor path when keys match).
|
|
1844
|
+
*/
|
|
1845
|
+
function sharedSecretFromRecipientPreimage(ecdhShared, preimage) {
|
|
1846
|
+
const out = ecdhShared(preimage.recipientScalar, preimage.ephemeralKey.x, preimage.ephemeralKey.y);
|
|
1847
|
+
return { x: out.x, y: out.y };
|
|
1848
|
+
}
|
|
1849
|
+
|
|
1850
|
+
/** Stroops amount as WASM `u64` (`bigint`). */
|
|
1851
|
+
function wasmU64Stroops(amount) {
|
|
1852
|
+
const b = typeof amount === 'bigint' ? amount : BigInt(amount);
|
|
1853
|
+
if (b < 0n || b > 0xffffffffffffffffn) {
|
|
1854
|
+
throw new RangeError('amount must be a non-negative u64 (stroops)');
|
|
1855
|
+
}
|
|
1856
|
+
return b;
|
|
1857
|
+
}
|
|
1093
1858
|
class PrivacyPoolSDK {
|
|
1094
1859
|
constructor(wasm, options) {
|
|
1095
1860
|
this.wasm = wasm;
|
|
@@ -1114,20 +1879,70 @@ class PrivacyPoolSDK {
|
|
|
1114
1879
|
return new PrivacyPoolSDK(wasm, opts);
|
|
1115
1880
|
}
|
|
1116
1881
|
/**
|
|
1117
|
-
*
|
|
1882
|
+
* Uniform 32-byte scalar as lowercase hex (Web Crypto). Same in browser and Node 19+.
|
|
1883
|
+
*/
|
|
1884
|
+
static generateRandomScalarHex32() {
|
|
1885
|
+
return generateRandomScalarHex32();
|
|
1886
|
+
}
|
|
1887
|
+
/**
|
|
1888
|
+
* Text to sign with a Stellar wallet for stealth derivation (UTF-8). No WASM required.
|
|
1889
|
+
*/
|
|
1890
|
+
static buildStealthAddressSignMessage(address, nonce = DEFAULT_STEALTH_SIGN_NONCE) {
|
|
1891
|
+
return buildStealthAddressSignMessage(address, nonce);
|
|
1892
|
+
}
|
|
1893
|
+
/**
|
|
1894
|
+
* Generate a new coin with random nullifier, secret, and random shared-secret field elements (dev / self-contained tests).
|
|
1895
|
+
* @param amount Stroops encoded as `bigint` or integer `number` (WASM `u64`).
|
|
1896
|
+
*/
|
|
1897
|
+
generateCoin(amount) {
|
|
1898
|
+
return this.wasm.generateCoin(wasmU64Stroops(amount));
|
|
1899
|
+
}
|
|
1900
|
+
/**
|
|
1901
|
+
* Generate a coin with the same commitment shape as on-chain deposit: pass `ecdhSharedKey` output (hex x, y).
|
|
1902
|
+
* @param amount Stroops (`bigint` | `number`).
|
|
1903
|
+
*/
|
|
1904
|
+
generateCoinWithSharedSecret(shared, amount) {
|
|
1905
|
+
return this.wasm.generateCoinWithSharedSecretHex(shared.x, shared.y, wasmU64Stroops(amount));
|
|
1906
|
+
}
|
|
1907
|
+
/**
|
|
1908
|
+
* Coin for a depositor `ephemeralKeyScalar` (32-byte hex): `coin.secret = Poseidon255(1)(scalar)` as in `deposit.circom`.
|
|
1909
|
+
* @param amount Stroops (`bigint` | `number`).
|
|
1118
1910
|
*/
|
|
1119
|
-
|
|
1120
|
-
return this.wasm.
|
|
1911
|
+
generateCoinFromDepositEphemeralScalarHex(scalarHex, amount) {
|
|
1912
|
+
return this.wasm.generateCoinFromDepositEphemeralScalarHex(scalarHex, wasmU64Stroops(amount));
|
|
1121
1913
|
}
|
|
1122
1914
|
/**
|
|
1123
|
-
*
|
|
1915
|
+
* Aligned deposit coin: `secret = Poseidon₁(scalar)` and ECDH shared key from hex coords (e.g. `ecdhSharedKey(scalar, recipient_x, recipient_y)`).
|
|
1916
|
+
* @param amount Stroops (`bigint` | `number`).
|
|
1124
1917
|
*/
|
|
1125
|
-
|
|
1918
|
+
generateCoinForDepositWithSharedHex(scalarHex, sharedXHex, sharedYHex, amount) {
|
|
1919
|
+
return this.wasm.generateCoinForDepositWithSharedHex(scalarHex, sharedXHex, sharedYHex, wasmU64Stroops(amount));
|
|
1920
|
+
}
|
|
1921
|
+
/**
|
|
1922
|
+
* Merkle root, path, and coin fields for the first withdraw leg (Rust LeanIMT + Poseidon).
|
|
1923
|
+
*/
|
|
1924
|
+
buildWithdrawMerkleWitness(coin, state) {
|
|
1126
1925
|
const coinJson = JSON.stringify(coin);
|
|
1127
1926
|
const stateJson = JSON.stringify(state);
|
|
1128
|
-
const resultJson = this.wasm.
|
|
1927
|
+
const resultJson = this.wasm.buildWithdrawMerkleWitness(coinJson, stateJson);
|
|
1129
1928
|
return JSON.parse(resultJson);
|
|
1130
1929
|
}
|
|
1930
|
+
/**
|
|
1931
|
+
* Full `Transaction(20,2,2)` withdrawal proof: one real withdraw + dummies, using coin/state and depositor ECDH point (hex).
|
|
1932
|
+
*/
|
|
1933
|
+
async proveWithdrawal(coin, state, params) {
|
|
1934
|
+
const witness = this.buildWithdrawMerkleWitness(coin, state);
|
|
1935
|
+
const w0 = withdrawObjectFromMerkleWitness(witness, {
|
|
1936
|
+
x: params.ephemeralXHex,
|
|
1937
|
+
y: params.ephemeralYHex,
|
|
1938
|
+
});
|
|
1939
|
+
return this.proveTransaction({
|
|
1940
|
+
stateRoot: witness.stateRoot,
|
|
1941
|
+
withdrawAddressHi: params.withdrawAddressHi,
|
|
1942
|
+
withdrawAddressLo: params.withdrawAddressLo,
|
|
1943
|
+
privKeyScalar: params.privKeyScalar,
|
|
1944
|
+
}, [w0, 'dummy'], ['dummy', 'dummy']);
|
|
1945
|
+
}
|
|
1131
1946
|
/**
|
|
1132
1947
|
* Convert a snarkjs proof JSON to hex bytes for Soroban.
|
|
1133
1948
|
*/
|
|
@@ -1141,16 +1956,33 @@ class PrivacyPoolSDK {
|
|
|
1141
1956
|
return this.wasm.publicToHex(JSON.stringify(publicSignals));
|
|
1142
1957
|
}
|
|
1143
1958
|
/**
|
|
1144
|
-
*
|
|
1145
|
-
|
|
1959
|
+
* BabyJubJub ephemeral point from a 32-byte scalar (hex). For custom {@link WithdrawObject} / tests.
|
|
1960
|
+
*/
|
|
1961
|
+
ecdhEphemeralPublicKeyFromScalarHex(scalarHex) {
|
|
1962
|
+
return this.wasm.ecdhEphemeralPublicKeyFromScalarHex(scalarHex);
|
|
1963
|
+
}
|
|
1964
|
+
/** Circuit `ECDH`: scalar (32-byte hex) × recipient BabyJub point → shared key hex coords. */
|
|
1965
|
+
ecdhSharedKey(scalarHex, recipientPubXHex, recipientPubYHex) {
|
|
1966
|
+
return this.wasm.ecdhSharedKey(scalarHex, recipientPubXHex, recipientPubYHex);
|
|
1967
|
+
}
|
|
1968
|
+
/**
|
|
1969
|
+
* `Transaction(20,2,2)` proof from high-level legs: maps to witness input (incl. `"dummy"` ECDH via WASM), then Groth16 → Soroban hex.
|
|
1970
|
+
*
|
|
1971
|
+
* @param publicParams Public inputs: `stateRoot`, `withdrawAddressHi` / `withdrawAddressLo`, `privKeyScalar` (decimal field strings).
|
|
1972
|
+
* @param withdraws Exactly two withdraw slots (`WithdrawObject` or `"dummy"`).
|
|
1973
|
+
* @param deposits Exactly two deposit slots (`DepositObject` or `"dummy"`).
|
|
1146
1974
|
*/
|
|
1147
|
-
async
|
|
1148
|
-
const
|
|
1149
|
-
|
|
1975
|
+
async proveTransaction(publicParams, withdraws, deposits) {
|
|
1976
|
+
const wasmEcdh = {
|
|
1977
|
+
ecdhEphemeralPublicKeyFromScalarHex: (h) => this.wasm.ecdhEphemeralPublicKeyFromScalarHex(h),
|
|
1978
|
+
};
|
|
1979
|
+
const witnessInput = buildTransactionWitnessInput(publicParams, withdraws, deposits, wasmEcdh);
|
|
1980
|
+
const wtns = await generateWitness(witnessInput, this.options.circuitWasm);
|
|
1150
1981
|
const { proof, publicSignals } = await generateProof(wtns, this.options.zkey);
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1982
|
+
return {
|
|
1983
|
+
proof_hex: this.proofToHex(proof),
|
|
1984
|
+
public_hex: this.publicToHex(publicSignals),
|
|
1985
|
+
};
|
|
1154
1986
|
}
|
|
1155
1987
|
/**
|
|
1156
1988
|
* Calculate nullifier hash: Poseidon(nullifier)
|
|
@@ -1160,8 +1992,37 @@ class PrivacyPoolSDK {
|
|
|
1160
1992
|
calculateNullifierHash(nullifier) {
|
|
1161
1993
|
return this.wasm.calculateNullifierHash(nullifier);
|
|
1162
1994
|
}
|
|
1995
|
+
/**
|
|
1996
|
+
* Ed25519 signature from signing {@link buildStealthAddressSignMessage}: **128 hex chars** (optional `0x`)
|
|
1997
|
+
* or **base64** (64 raw bytes after decode). `SHA-256(signature bytes)` → scalar → ECDH → `stpl1` Bech32.
|
|
1998
|
+
*/
|
|
1999
|
+
async generateStealthAddressFromStellarSignature(signature) {
|
|
2000
|
+
return stealthAddressFromStellarSignature((h) => this.wasm.ecdhEphemeralPublicKeyFromScalarHex(h), encodeStealthAddress, signature);
|
|
2001
|
+
}
|
|
2002
|
+
encodeDecodedEphemeralKey(decoded) {
|
|
2003
|
+
return encodeDecodedEphemeralKey(decoded);
|
|
2004
|
+
}
|
|
2005
|
+
decodeDecodedEphemeralKey(encoded) {
|
|
2006
|
+
return decodeDecodedEphemeralKey(encoded);
|
|
2007
|
+
}
|
|
2008
|
+
encodeDepositorSharedSecretPreimage(decoded) {
|
|
2009
|
+
return encodeDepositorSharedSecretPreimage(decoded);
|
|
2010
|
+
}
|
|
2011
|
+
decodeDepositorSharedSecretPreimage(encoded) {
|
|
2012
|
+
return decodeDepositorSharedSecretPreimage(encoded);
|
|
2013
|
+
}
|
|
2014
|
+
sharedSecretFromDepositorPreimage(preimage) {
|
|
2015
|
+
return sharedSecretFromDepositorPreimage((a, b, c) => this.wasm.ecdhSharedKey(a, b, c), preimage);
|
|
2016
|
+
}
|
|
2017
|
+
sharedSecretFromRecipientPreimage(preimage) {
|
|
2018
|
+
return sharedSecretFromRecipientPreimage((a, b, c) => this.wasm.ecdhSharedKey(a, b, c), preimage);
|
|
2019
|
+
}
|
|
1163
2020
|
}
|
|
1164
2021
|
|
|
2022
|
+
/** Pool Merkle tree depth (matches `coin::TREE_DEPTH` / `Transaction` circuit). */
|
|
2023
|
+
/** Default coin value in stroops (1 XLM); matches Rust `coin::COIN_VALUE`. */
|
|
2024
|
+
const COIN_VALUE_STROOPS = 1000000000;
|
|
2025
|
+
|
|
1165
2026
|
async function main() {
|
|
1166
2027
|
const args = process.argv.slice(2);
|
|
1167
2028
|
if (args.length === 0 || args[0] === '--help' || args[0] === '-h') {
|
|
@@ -1172,9 +2033,24 @@ async function main() {
|
|
|
1172
2033
|
if (command === 'withdraw') {
|
|
1173
2034
|
await handleWithdraw(args.slice(1));
|
|
1174
2035
|
}
|
|
2036
|
+
else if (command === 'deposit-proof') {
|
|
2037
|
+
await handleDepositProof(args.slice(1));
|
|
2038
|
+
}
|
|
1175
2039
|
else if (command === 'generate') {
|
|
1176
2040
|
await handleGenerate(args.slice(1));
|
|
1177
2041
|
}
|
|
2042
|
+
else if (command === 'random-scalar') {
|
|
2043
|
+
handleRandomScalar();
|
|
2044
|
+
}
|
|
2045
|
+
else if (command === 'stealth-sign-message') {
|
|
2046
|
+
handleStealthSignMessage(args.slice(1));
|
|
2047
|
+
}
|
|
2048
|
+
else if (command === 'stealth-from-signature') {
|
|
2049
|
+
await handleStealthFromSignature(args.slice(1));
|
|
2050
|
+
}
|
|
2051
|
+
else if (command === 'priv-scalar-from-signature') {
|
|
2052
|
+
await handlePrivScalarFromSignature(args.slice(1));
|
|
2053
|
+
}
|
|
1178
2054
|
else {
|
|
1179
2055
|
console.error(`Unknown command: ${command}`);
|
|
1180
2056
|
printUsage();
|
|
@@ -1189,14 +2065,44 @@ function printUsage() {
|
|
|
1189
2065
|
Commands:
|
|
1190
2066
|
generate Generate a new coin
|
|
1191
2067
|
--output, -o <file> Output coin to file (default: stdout)
|
|
2068
|
+
--amount <stroops> Coin value in stroops (u64); default: 1000000000 (1 XLM)
|
|
2069
|
+
--scalar <hex> 32-byte depositor ephemeral scalar (64 hex, optional 0x); coin.secret = Poseidon₁(scalar) (deposit.circom)
|
|
2070
|
+
--stealth <stpl1...> With --scalar: ECDH(scalar, recipient) shared secret + aligned commitment (requires WASM ecdhSharedKey)
|
|
2071
|
+
|
|
2072
|
+
random-scalar Print random 32-byte hex scalar with integer < 2^253 (BabyJub / circom)
|
|
2073
|
+
|
|
2074
|
+
stealth-sign-message Print message to sign (Stellar wallet / stellar CLI)
|
|
2075
|
+
--address <G...> Stellar account address (required)
|
|
2076
|
+
--nonce <string> Nonce label (default: "main address")
|
|
2077
|
+
|
|
2078
|
+
stealth-from-signature Derive stpl1 stealth address from Ed25519 signature
|
|
2079
|
+
--signature <value> 128 hex chars (optional 0x) or standard base64 (64 bytes)
|
|
2080
|
+
--signature-file <path> Read signature from file (whitespace trimmed)
|
|
2081
|
+
|
|
2082
|
+
priv-scalar-from-signature Print privKeyScalar (decimal Fr) from Stellar Ed25519 signature (SHA-256(sig) mod r)
|
|
1192
2083
|
|
|
1193
2084
|
withdraw Generate a withdrawal proof
|
|
1194
2085
|
--coin <file> Path to coin JSON file
|
|
1195
2086
|
--state <file> Path to state JSON file
|
|
2087
|
+
--withdraw-pubkey-hex <hex> Stellar account Ed25519 payload (32 bytes = 64 hex); splits to public withdrawAddressHi/Lo
|
|
2088
|
+
--withdraw-address-hi <dec> Optional: override high u128 (decimal) if not using --withdraw-pubkey-hex
|
|
2089
|
+
--withdraw-address-lo <dec> Optional: override low u128 (decimal)
|
|
2090
|
+
--priv-key-scalar <dec> privKeyScalar (decimal Fr)
|
|
2091
|
+
--ephemeral-x <hex> Depositor ECDH point x (64 hex chars, optional 0x)
|
|
2092
|
+
--ephemeral-y <hex> Depositor ECDH point y (64 hex chars, optional 0x)
|
|
1196
2093
|
--output-proof <file> Write proof hex to file
|
|
1197
2094
|
--output-public <file> Write public signals hex to file
|
|
1198
2095
|
|
|
1199
|
-
|
|
2096
|
+
deposit-proof Groth16 proof for deposit-only transact (2 dummy withdraws, 1 deposit + dummy)
|
|
2097
|
+
--state-root <dec> Current Merkle root (decimal Fr), must match pool on submit
|
|
2098
|
+
--stealth <stpl1...> Recipient stealth address (decodes to recipient public key)
|
|
2099
|
+
--coin <file> With --ephemeral-scalar-hex: use coin nullifier/value (aligned with generate --scalar --stealth)
|
|
2100
|
+
--ephemeral-scalar-hex <hex> Same 32-byte hex as deposit / generate --scalar
|
|
2101
|
+
--value <dec> Deposit amount (stroops as decimal Fr); optional if --coin (must match coin)
|
|
2102
|
+
--output-proof <file> Write proof hex to file
|
|
2103
|
+
--output-public <file> Write public signals hex to file
|
|
2104
|
+
|
|
2105
|
+
Output (withdraw, deposit-proof):
|
|
1200
2106
|
Prints proof_hex on first line and public_hex on second line to stdout.
|
|
1201
2107
|
`);
|
|
1202
2108
|
}
|
|
@@ -1218,13 +2124,101 @@ function parseArgs(args) {
|
|
|
1218
2124
|
else if (arg === '-o' && i + 1 < args.length) {
|
|
1219
2125
|
parsed['output'] = args[++i];
|
|
1220
2126
|
}
|
|
2127
|
+
else if (arg === '-a' && i + 1 < args.length) {
|
|
2128
|
+
parsed['address'] = args[++i];
|
|
2129
|
+
}
|
|
2130
|
+
else if (arg === '-n' && i + 1 < args.length) {
|
|
2131
|
+
parsed['nonce'] = args[++i];
|
|
2132
|
+
}
|
|
2133
|
+
else if (arg === '-s' && i + 1 < args.length) {
|
|
2134
|
+
parsed['signature'] = args[++i];
|
|
2135
|
+
}
|
|
1221
2136
|
}
|
|
1222
2137
|
return parsed;
|
|
1223
2138
|
}
|
|
2139
|
+
function handleStealthSignMessage(args) {
|
|
2140
|
+
const parsed = parseArgs(args);
|
|
2141
|
+
const address = parsed['address'];
|
|
2142
|
+
if (!address) {
|
|
2143
|
+
console.error('Error: --address <G...> is required');
|
|
2144
|
+
process.exit(1);
|
|
2145
|
+
}
|
|
2146
|
+
const nonce = parsed['nonce'] ?? DEFAULT_STEALTH_SIGN_NONCE;
|
|
2147
|
+
console.log(buildStealthAddressSignMessage(address, nonce));
|
|
2148
|
+
}
|
|
2149
|
+
async function handleStealthFromSignature(args) {
|
|
2150
|
+
const parsed = parseArgs(args);
|
|
2151
|
+
let sig = parsed['signature'];
|
|
2152
|
+
if (parsed['signature-file']) {
|
|
2153
|
+
sig = fs__namespace.readFileSync(parsed['signature-file'], 'utf-8');
|
|
2154
|
+
}
|
|
2155
|
+
if (!sig) {
|
|
2156
|
+
console.error('Error: --signature <hex> or --signature-file <path> is required');
|
|
2157
|
+
process.exit(1);
|
|
2158
|
+
}
|
|
2159
|
+
const sdk = await PrivacyPoolSDK.init();
|
|
2160
|
+
const stealth = await sdk.generateStealthAddressFromStellarSignature(sig);
|
|
2161
|
+
console.log(stealth);
|
|
2162
|
+
}
|
|
2163
|
+
async function handlePrivScalarFromSignature(args) {
|
|
2164
|
+
const parsed = parseArgs(args);
|
|
2165
|
+
let sig = parsed['signature'];
|
|
2166
|
+
if (parsed['signature-file']) {
|
|
2167
|
+
sig = fs__namespace.readFileSync(parsed['signature-file'], 'utf-8');
|
|
2168
|
+
}
|
|
2169
|
+
if (!sig) {
|
|
2170
|
+
console.error('Error: --signature <hex> or --signature-file <path> is required');
|
|
2171
|
+
process.exit(1);
|
|
2172
|
+
}
|
|
2173
|
+
const dec = await privKeyScalarDecimalFromStellarSignature(sig.trim());
|
|
2174
|
+
console.log(dec);
|
|
2175
|
+
}
|
|
2176
|
+
function handleRandomScalar() {
|
|
2177
|
+
console.log(PrivacyPoolSDK.generateRandomScalarHex32());
|
|
2178
|
+
}
|
|
2179
|
+
function parseStroopsU64(label, raw, defaultStroops) {
|
|
2180
|
+
if (raw === undefined) {
|
|
2181
|
+
return defaultStroops;
|
|
2182
|
+
}
|
|
2183
|
+
if (!/^\d+$/.test(raw)) {
|
|
2184
|
+
console.error(`Error: ${label} must be a non-negative decimal integer (stroops u64)`);
|
|
2185
|
+
process.exit(1);
|
|
2186
|
+
}
|
|
2187
|
+
try {
|
|
2188
|
+
const b = BigInt(raw);
|
|
2189
|
+
if (b < 0n || b > 0xffffffffffffffffn) {
|
|
2190
|
+
console.error(`Error: ${label} out of u64 range`);
|
|
2191
|
+
process.exit(1);
|
|
2192
|
+
}
|
|
2193
|
+
return b;
|
|
2194
|
+
}
|
|
2195
|
+
catch {
|
|
2196
|
+
console.error(`Error: invalid ${label}`);
|
|
2197
|
+
process.exit(1);
|
|
2198
|
+
}
|
|
2199
|
+
}
|
|
1224
2200
|
async function handleGenerate(args) {
|
|
1225
2201
|
const parsed = parseArgs(args);
|
|
1226
2202
|
const sdk = await PrivacyPoolSDK.init();
|
|
1227
|
-
const
|
|
2203
|
+
const scalar = parsed['scalar'];
|
|
2204
|
+
const stealth = parsed['stealth'];
|
|
2205
|
+
const amount = parseStroopsU64('--amount', parsed['amount'], BigInt(COIN_VALUE_STROOPS));
|
|
2206
|
+
if (stealth && !scalar) {
|
|
2207
|
+
console.error('Error: --stealth requires --scalar');
|
|
2208
|
+
process.exit(1);
|
|
2209
|
+
}
|
|
2210
|
+
let coin;
|
|
2211
|
+
if (scalar && stealth) {
|
|
2212
|
+
const { x, y } = decodeStealthAddress(stealth);
|
|
2213
|
+
const shared = sdk.ecdhSharedKey(scalar, x, y);
|
|
2214
|
+
coin = sdk.generateCoinForDepositWithSharedHex(scalar, shared.x, shared.y, amount);
|
|
2215
|
+
}
|
|
2216
|
+
else if (scalar) {
|
|
2217
|
+
coin = sdk.generateCoinFromDepositEphemeralScalarHex(scalar, amount);
|
|
2218
|
+
}
|
|
2219
|
+
else {
|
|
2220
|
+
coin = sdk.generateCoin(amount);
|
|
2221
|
+
}
|
|
1228
2222
|
const json = JSON.stringify(coin, null, 2);
|
|
1229
2223
|
if (parsed['output']) {
|
|
1230
2224
|
fs__namespace.writeFileSync(parsed['output'], json);
|
|
@@ -1245,11 +2239,37 @@ async function handleWithdraw(args) {
|
|
|
1245
2239
|
console.error('Error: --state <file> is required');
|
|
1246
2240
|
process.exit(1);
|
|
1247
2241
|
}
|
|
2242
|
+
let withdrawHi = parsed['withdraw-address-hi'];
|
|
2243
|
+
let withdrawLo = parsed['withdraw-address-lo'];
|
|
2244
|
+
const pkHex = parsed['withdraw-pubkey-hex'];
|
|
2245
|
+
if (pkHex) {
|
|
2246
|
+
const parts = ed25519PubkeyPayloadHexToWithdrawFrDecimals(pkHex);
|
|
2247
|
+
withdrawHi = parts.hi;
|
|
2248
|
+
withdrawLo = parts.lo;
|
|
2249
|
+
}
|
|
2250
|
+
if (withdrawHi === undefined || withdrawLo === undefined) {
|
|
2251
|
+
console.error('Error: provide --withdraw-pubkey-hex <64 hex> or both --withdraw-address-hi and --withdraw-address-lo');
|
|
2252
|
+
process.exit(1);
|
|
2253
|
+
}
|
|
2254
|
+
if (!parsed['priv-key-scalar']) {
|
|
2255
|
+
console.error('Error: --priv-key-scalar <dec> is required');
|
|
2256
|
+
process.exit(1);
|
|
2257
|
+
}
|
|
2258
|
+
if (!parsed['ephemeral-x'] || !parsed['ephemeral-y']) {
|
|
2259
|
+
console.error('Error: --ephemeral-x <hex> and --ephemeral-y <hex> are required');
|
|
2260
|
+
process.exit(1);
|
|
2261
|
+
}
|
|
1248
2262
|
const coinFile = JSON.parse(fs__namespace.readFileSync(parsed['coin'], 'utf-8'));
|
|
1249
2263
|
const coin = coinFile.coin || coinFile;
|
|
1250
2264
|
const state = JSON.parse(fs__namespace.readFileSync(parsed['state'], 'utf-8'));
|
|
1251
2265
|
const sdk = await PrivacyPoolSDK.init();
|
|
1252
|
-
const result = await sdk.
|
|
2266
|
+
const result = await sdk.proveWithdrawal(coin, state, {
|
|
2267
|
+
withdrawAddressHi: withdrawHi,
|
|
2268
|
+
withdrawAddressLo: withdrawLo,
|
|
2269
|
+
privKeyScalar: parsed['priv-key-scalar'],
|
|
2270
|
+
ephemeralXHex: parsed['ephemeral-x'],
|
|
2271
|
+
ephemeralYHex: parsed['ephemeral-y'],
|
|
2272
|
+
});
|
|
1253
2273
|
// Output proof and public hex to stdout (newline-separated)
|
|
1254
2274
|
console.log(result.proof_hex);
|
|
1255
2275
|
console.log(result.public_hex);
|
|
@@ -1263,6 +2283,69 @@ async function handleWithdraw(args) {
|
|
|
1263
2283
|
console.error(`Public signals written to: ${parsed['output-public']}`);
|
|
1264
2284
|
}
|
|
1265
2285
|
}
|
|
2286
|
+
async function handleDepositProof(args) {
|
|
2287
|
+
const parsed = parseArgs(args);
|
|
2288
|
+
if (!parsed['state-root']) {
|
|
2289
|
+
console.error('Error: --state-root <dec> is required');
|
|
2290
|
+
process.exit(1);
|
|
2291
|
+
}
|
|
2292
|
+
if (!parsed['stealth']) {
|
|
2293
|
+
console.error('Error: --stealth <stpl1...> is required');
|
|
2294
|
+
process.exit(1);
|
|
2295
|
+
}
|
|
2296
|
+
const sdk = await PrivacyPoolSDK.init();
|
|
2297
|
+
const recipientPublicKeys = recipientPublicKeysDecimalFromStealthAddress(parsed['stealth']);
|
|
2298
|
+
const coinPath = parsed['coin'];
|
|
2299
|
+
const ephemeralScalarHex = parsed['ephemeral-scalar-hex'];
|
|
2300
|
+
let deposit;
|
|
2301
|
+
if (coinPath || ephemeralScalarHex) {
|
|
2302
|
+
if (!coinPath || !ephemeralScalarHex) {
|
|
2303
|
+
console.error('Error: aligned deposit proof requires both --coin <file> and --ephemeral-scalar-hex <hex>');
|
|
2304
|
+
process.exit(1);
|
|
2305
|
+
}
|
|
2306
|
+
const coinFile = JSON.parse(fs__namespace.readFileSync(coinPath, 'utf-8'));
|
|
2307
|
+
const c = coinFile.coin || coinFile;
|
|
2308
|
+
const value = parsed['value'] ?? c.value;
|
|
2309
|
+
if (parsed['value'] && parsed['value'] !== c.value) {
|
|
2310
|
+
console.error('Error: --value must match coin.value when using --coin');
|
|
2311
|
+
process.exit(1);
|
|
2312
|
+
}
|
|
2313
|
+
deposit = {
|
|
2314
|
+
value,
|
|
2315
|
+
nullifier: c.nullifier,
|
|
2316
|
+
ephemeralKeyScalar: scalarHexToFrDecimal(ephemeralScalarHex),
|
|
2317
|
+
recipientPublicKeys,
|
|
2318
|
+
};
|
|
2319
|
+
}
|
|
2320
|
+
else {
|
|
2321
|
+
if (!parsed['value']) {
|
|
2322
|
+
console.error('Error: --value <dec> is required (unless using --coin and --ephemeral-scalar-hex)');
|
|
2323
|
+
process.exit(1);
|
|
2324
|
+
}
|
|
2325
|
+
deposit = {
|
|
2326
|
+
value: parsed['value'],
|
|
2327
|
+
nullifier: randomFrDecimal(),
|
|
2328
|
+
ephemeralKeyScalar: randomFrDecimal253(),
|
|
2329
|
+
recipientPublicKeys,
|
|
2330
|
+
};
|
|
2331
|
+
}
|
|
2332
|
+
const result = await sdk.proveTransaction({
|
|
2333
|
+
stateRoot: parsed['state-root'],
|
|
2334
|
+
withdrawAddressHi: '0',
|
|
2335
|
+
withdrawAddressLo: '0',
|
|
2336
|
+
privKeyScalar: randomFrDecimal253(),
|
|
2337
|
+
}, ['dummy', 'dummy'], [deposit, 'dummy']);
|
|
2338
|
+
console.log(result.proof_hex);
|
|
2339
|
+
console.log(result.public_hex);
|
|
2340
|
+
if (parsed['output-proof']) {
|
|
2341
|
+
fs__namespace.writeFileSync(parsed['output-proof'], result.proof_hex);
|
|
2342
|
+
console.error(`Proof written to: ${parsed['output-proof']}`);
|
|
2343
|
+
}
|
|
2344
|
+
if (parsed['output-public']) {
|
|
2345
|
+
fs__namespace.writeFileSync(parsed['output-public'], result.public_hex);
|
|
2346
|
+
console.error(`Public signals written to: ${parsed['output-public']}`);
|
|
2347
|
+
}
|
|
2348
|
+
}
|
|
1266
2349
|
main().catch((err) => {
|
|
1267
2350
|
console.error('Error:', err.message || err);
|
|
1268
2351
|
process.exit(1);
|