@idos-network/enclave 1.5.0 → 2.2.2

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.
@@ -1,1197 +0,0 @@
1
- import nacl from "tweetnacl";
2
- import { WALLET_TYPES } from "@idos-network/kwil-infra/actions";
3
- import { ChainControllerApi, Configuration } from "@partisiablockchain/blockchain-api-transaction-client";
4
- import { ethers } from "ethers";
5
- import { AbiByteInput } from "@partisiablockchain/abi-client";
6
- import { randomBytes } from "crypto";
7
- import invariant from "tiny-invariant";
8
- //#region src/mpc/api.ts
9
- const postHeaders = {
10
- Accept: "application/json, text/plain, */*",
11
- "Content-Type": "application/json"
12
- };
13
- function buildOptions(method, headers, entityBytes) {
14
- const result = {
15
- method,
16
- headers,
17
- body: null
18
- };
19
- if (entityBytes != null) result.body = JSON.stringify(entityBytes);
20
- return result;
21
- }
22
- /**
23
- * Make a http put-request.
24
- *
25
- * @param url the url to request.
26
- * @param object the object to put.
27
- * @param headers
28
- * @return a promise containing whether the put succeeded or not.
29
- */
30
- function putRequest(url, object, headers) {
31
- const options = buildOptions("PUT", {
32
- ...postHeaders,
33
- ...headers
34
- }, object);
35
- return fetch(url, options).then(async (response) => {
36
- const responseBody = await response.clone().text();
37
- console.log({
38
- responseCode: response.status,
39
- responseBody
40
- });
41
- return response.status.toString();
42
- }).catch((error) => {
43
- console.error(error);
44
- return error;
45
- });
46
- }
47
- /**
48
- * Make a http patch-request.
49
- *
50
- * @param url the url to request.
51
- * @param object the object to put.
52
- * @param headers
53
- * @return a promise containing whether the put succeeded or not.
54
- */
55
- function patchRequest(url, object, headers) {
56
- const options = buildOptions("PATCH", {
57
- ...postHeaders,
58
- ...headers
59
- }, object);
60
- return fetch(url, options).then(async (response) => {
61
- const responseBody = await response.clone().text();
62
- console.log({
63
- responseCode: response.status,
64
- responseBody
65
- });
66
- return response.status.toString();
67
- }).catch((error) => {
68
- console.error(error);
69
- return error;
70
- });
71
- }
72
- /**
73
- * Make a http post-request.
74
- *
75
- * @param url the url to request.
76
- * @param object the object to post.
77
- * @param headers
78
- * @return a promise containing the result of the post request.
79
- */
80
- function postRequest(url, object, headers) {
81
- const options = buildOptions("POST", {
82
- ...postHeaders,
83
- ...headers
84
- }, object);
85
- return handleFetch(fetch(url, options));
86
- }
87
- function handleFetch(promise) {
88
- return promise.then(async (response) => {
89
- const responseBody = await response.clone().text();
90
- console.log({
91
- responseCode: response.status,
92
- responseBody
93
- });
94
- if (response.status === 200) {
95
- const data = await response.json();
96
- return {
97
- status: response.status.toString(),
98
- body: data
99
- };
100
- }
101
- return {
102
- status: response.status.toString(),
103
- body: void 0
104
- };
105
- }).catch((error) => {
106
- console.error(error);
107
- return {
108
- status: "fetch-error",
109
- body: void 0
110
- };
111
- });
112
- }
113
- //#endregion
114
- //#region src/mpc/engine-client.ts
115
- var EngineClient = class {
116
- baseUrl;
117
- contractAddress;
118
- walletType;
119
- constructor(baseUrl, contractAddress, walletType) {
120
- this.contractAddress = contractAddress;
121
- this.baseUrl = baseUrl;
122
- this.walletType = walletType;
123
- }
124
- getAuthHeader(signature) {
125
- let prefix;
126
- switch (this.walletType) {
127
- case "EVM":
128
- prefix = "eip712";
129
- break;
130
- case "NEAR":
131
- prefix = "NEAR";
132
- break;
133
- case "XRPL":
134
- prefix = "XRPL";
135
- break;
136
- case "FaceSign":
137
- prefix = "FACESIGN";
138
- break;
139
- default: prefix = "eip712";
140
- }
141
- return { Authorization: `${prefix} ${signature}` };
142
- }
143
- async sendUpload(id, uploadRequest, signature) {
144
- const authHeader = this.getAuthHeader(signature);
145
- const url = `${this.baseUrl}/offchain/${this.contractAddress}/shares/${id}`;
146
- const status = await putRequest(url, uploadRequest, authHeader);
147
- if (status !== "201") throw new Error(`Error uploading share to ${this.contractAddress} at ${url}`);
148
- return status;
149
- }
150
- async sendDownload(id, downloadRequest, signature) {
151
- const authHeader = this.getAuthHeader(signature);
152
- return await postRequest(`${this.baseUrl}/offchain/${this.contractAddress}/shares/${id}`, downloadRequest, authHeader);
153
- }
154
- async downloadAndDecrypt(id, downloadRequest, signature, secretKey) {
155
- const { status, body: encryptedShare } = await this.sendDownload(id, downloadRequest, signature);
156
- if (encryptedShare === void 0) return {
157
- share: void 0,
158
- status
159
- };
160
- const encryptedBuffer = ethers.getBytes(encryptedShare.encrypted_share);
161
- const publicKeyBuffer = ethers.getBytes(encryptedShare.public_key);
162
- const nonceBuffer = ethers.getBytes(encryptedShare.nonce);
163
- const open = nacl.box.open(encryptedBuffer, nonceBuffer, publicKeyBuffer, secretKey);
164
- if (open == null) return {
165
- share: void 0,
166
- status: "box-open-error"
167
- };
168
- return {
169
- share: Buffer.from(open.subarray(32)),
170
- status
171
- };
172
- }
173
- async sendUpdate(id, updateRequest, signature) {
174
- const authHeader = { Authorization: `eip712 ${signature}` };
175
- const url = `${this.baseUrl}/offchain/${this.contractAddress}/shares/${id}`;
176
- const ok = await patchRequest(url, updateRequest, authHeader);
177
- if (!ok) throw new Error(`Error updating wallets to ${this.contractAddress} at ${url}`);
178
- return ok;
179
- }
180
- async sendAddAddress(id, addRequest, signature) {
181
- const authHeader = this.getAuthHeader(signature);
182
- const url = `${this.baseUrl}/offchain/${this.contractAddress}/shares/${id}/add_address`;
183
- const status = await patchRequest(url, addRequest, authHeader);
184
- if (status !== "200") throw new Error(`Error adding a wallet to ${id} at ${url}`);
185
- return status;
186
- }
187
- async sendRemoveAddress(id, removeRequest, signature) {
188
- const authHeader = this.getAuthHeader(signature);
189
- const url = `${this.baseUrl}/offchain/${this.contractAddress}/shares/${id}/remove_address`;
190
- const status = await patchRequest(url, removeRequest, authHeader);
191
- if (status !== "200") throw new Error(`Error removing address from ${id} at ${url}`);
192
- return status;
193
- }
194
- };
195
- //#endregion
196
- //#region src/mpc/generated/IdosContract.ts
197
- var IdosContract = class {
198
- _client;
199
- _address;
200
- constructor(client, address) {
201
- this._address = address;
202
- this._client = client;
203
- }
204
- deserializeContractState(_input) {
205
- const nodes_vecLength = _input.readI32();
206
- const nodes = [];
207
- for (let nodes_i = 0; nodes_i < nodes_vecLength; nodes_i++) {
208
- const nodes_elem = this.deserializeNodeConfig(_input);
209
- nodes.push(nodes_elem);
210
- }
211
- return { nodes };
212
- }
213
- deserializeNodeConfig(_input) {
214
- return {
215
- address: _input.readAddress(),
216
- endpoint: _input.readString()
217
- };
218
- }
219
- async getState() {
220
- const bytes = await this._client?.getContractStateBinary(this._address);
221
- if (bytes === void 0) throw new Error("Unable to get state bytes");
222
- const input = AbiByteInput.createLittleEndian(bytes);
223
- return this.deserializeContractState(input);
224
- }
225
- };
226
- function deserializeState(state, client, address) {
227
- if (Buffer.isBuffer(state)) {
228
- const input = AbiByteInput.createLittleEndian(state);
229
- return new IdosContract(client, address).deserializeContractState(input);
230
- }
231
- const input = AbiByteInput.createLittleEndian(state.bytes);
232
- return new IdosContract(state.client, state.address).deserializeContractState(input);
233
- }
234
- //#endregion
235
- //#region src/mpc/secretsharing/polynomial.ts
236
- /**
237
- * Polynomials with coefficients in a finite field.
238
- *
239
- * <p>Copied from <a href="https://gitlab.com/partisiablockchain/language/abi/zk-client"> zk-client</a>.
240
- */
241
- var Polynomial = class Polynomial {
242
- coefficients;
243
- constructor(coefficients) {
244
- this.coefficients = coefficients;
245
- }
246
- /**
247
- * Construct a polynomial from a set of coefficients. The degree of the resultant polynomial is
248
- * assumed to be equal to the number of coefficients minus 1. The constant term of the polynomial
249
- * is assumed to be stored in the first position of the coefficients.
250
- *
251
- * @param coefficients the coefficients of the polynomial
252
- * @param zero zero element of the field
253
- * @return the constructed polynomial
254
- */
255
- static create(coefficients, zero) {
256
- return new Polynomial(Polynomial.filterHighZeroes(coefficients, zero));
257
- }
258
- static filterHighZeroes(coefficients, zero) {
259
- for (let i = coefficients.length - 1; i >= 0; i--) if (!coefficients[i].isZero()) return coefficients.slice(0, i + 1);
260
- return [zero];
261
- }
262
- /**
263
- * Returns the coefficients of the polynomial.
264
- *
265
- * @return the coefficients of the polynomial
266
- */
267
- getCoefficients() {
268
- return this.coefficients.slice();
269
- }
270
- /**
271
- * Returns the degree of this polynomial.
272
- *
273
- * @return the degree of the polynomial
274
- */
275
- degree() {
276
- return this.coefficients.length - 1;
277
- }
278
- /**
279
- * Returns the constant term of the polynomial.
280
- *
281
- * @return the term stored on position 0 of the coefficients of this polynomial
282
- */
283
- getConstantTerm() {
284
- return this.coefficients[0];
285
- }
286
- /**
287
- * Evaluates this polynomial on a point. That is, if F is the polynomial and x a value, then this
288
- * method returns F(x).
289
- *
290
- * @param point the point to evaluate this polynomial on
291
- * @return F(point) where F is this polynomial
292
- */
293
- evaluate(point) {
294
- const degree = this.degree();
295
- let result = this.coefficients[degree];
296
- for (let i = degree - 1; i >= 0; --i) result = this.coefficients[i].add(point.multiply(result));
297
- return result;
298
- }
299
- };
300
- //#endregion
301
- //#region src/mpc/secretsharing/f256.ts
302
- /** Represents an element in GF(2^8) using the reduction polynomial x^8+x^4+x^3+x+1. */
303
- var F256 = class F256 {
304
- value;
305
- constructor(value) {
306
- this.value = value;
307
- }
308
- /**
309
- * The zero element.
310
- */
311
- static ZERO = F256.createElement(0);
312
- /**
313
- * The one element.
314
- */
315
- static ONE = F256.createElement(1);
316
- /**
317
- * Create a new field element with the given value.
318
- * @param value the value
319
- */
320
- static createElement(value) {
321
- return new F256(value & 255);
322
- }
323
- /**
324
- * Get the computation alphas for this field.
325
- * @returns the computation alphas
326
- */
327
- static alphas(numNodes) {
328
- return Array.from({ length: numNodes }, (_value, key) => F256.createElement(key + 1));
329
- }
330
- /**
331
- * Create a polynomial.
332
- * @param coefficients the coefficients of the polynomial
333
- */
334
- static createPoly(coefficients) {
335
- return Polynomial.create(coefficients, F256.ZERO);
336
- }
337
- /** @inheritDoc */
338
- add(other) {
339
- return Constants.elements[this.value ^ other.value];
340
- }
341
- /** @inheritDoc */
342
- isEqualTo(other) {
343
- return this.value === other.value;
344
- }
345
- /** @inheritDoc */
346
- isOne() {
347
- return this.value === 1;
348
- }
349
- /** @inheritDoc */
350
- isZero() {
351
- return this.value === 0;
352
- }
353
- /** @inheritDoc */
354
- modInverse() {
355
- return Constants.elements[Constants.multiplicativeInverse[this.value]];
356
- }
357
- /** @inheritDoc */
358
- multiply(other) {
359
- let a = this.value;
360
- let b = other.value;
361
- let m;
362
- let p = 0;
363
- for (let i = 0; i < 8; i++) {
364
- p = (p ^ -(b & 1) & a) & 255;
365
- m = -(a >> 7 & 1) & 255;
366
- a = (a << 1 ^ 283 & m) & 255;
367
- b = b >> 1;
368
- }
369
- return Constants.elements[p];
370
- }
371
- /** @inheritDoc */
372
- negate() {
373
- return this;
374
- }
375
- /** @inheritDoc */
376
- squareRoot() {
377
- throw new Error("Not implemented");
378
- }
379
- /** @inheritDoc */
380
- subtract(other) {
381
- return this.add(other);
382
- }
383
- };
384
- const Constants = {
385
- elements: Array.from({ length: 256 }, (_value, key) => F256.createElement(key)),
386
- multiplicativeInverse: [
387
- 0,
388
- 1,
389
- 141,
390
- 246,
391
- 203,
392
- 82,
393
- 123,
394
- 209,
395
- 232,
396
- 79,
397
- 41,
398
- 192,
399
- 176,
400
- 225,
401
- 229,
402
- 199,
403
- 116,
404
- 180,
405
- 170,
406
- 75,
407
- 153,
408
- 43,
409
- 96,
410
- 95,
411
- 88,
412
- 63,
413
- 253,
414
- 204,
415
- 255,
416
- 64,
417
- 238,
418
- 178,
419
- 58,
420
- 110,
421
- 90,
422
- 241,
423
- 85,
424
- 77,
425
- 168,
426
- 201,
427
- 193,
428
- 10,
429
- 152,
430
- 21,
431
- 48,
432
- 68,
433
- 162,
434
- 194,
435
- 44,
436
- 69,
437
- 146,
438
- 108,
439
- 243,
440
- 57,
441
- 102,
442
- 66,
443
- 242,
444
- 53,
445
- 32,
446
- 111,
447
- 119,
448
- 187,
449
- 89,
450
- 25,
451
- 29,
452
- 254,
453
- 55,
454
- 103,
455
- 45,
456
- 49,
457
- 245,
458
- 105,
459
- 167,
460
- 100,
461
- 171,
462
- 19,
463
- 84,
464
- 37,
465
- 233,
466
- 9,
467
- 237,
468
- 92,
469
- 5,
470
- 202,
471
- 76,
472
- 36,
473
- 135,
474
- 191,
475
- 24,
476
- 62,
477
- 34,
478
- 240,
479
- 81,
480
- 236,
481
- 97,
482
- 23,
483
- 22,
484
- 94,
485
- 175,
486
- 211,
487
- 73,
488
- 166,
489
- 54,
490
- 67,
491
- 244,
492
- 71,
493
- 145,
494
- 223,
495
- 51,
496
- 147,
497
- 33,
498
- 59,
499
- 121,
500
- 183,
501
- 151,
502
- 133,
503
- 16,
504
- 181,
505
- 186,
506
- 60,
507
- 182,
508
- 112,
509
- 208,
510
- 6,
511
- 161,
512
- 250,
513
- 129,
514
- 130,
515
- 131,
516
- 126,
517
- 127,
518
- 128,
519
- 150,
520
- 115,
521
- 190,
522
- 86,
523
- 155,
524
- 158,
525
- 149,
526
- 217,
527
- 247,
528
- 2,
529
- 185,
530
- 164,
531
- 222,
532
- 106,
533
- 50,
534
- 109,
535
- 216,
536
- 138,
537
- 132,
538
- 114,
539
- 42,
540
- 20,
541
- 159,
542
- 136,
543
- 249,
544
- 220,
545
- 137,
546
- 154,
547
- 251,
548
- 124,
549
- 46,
550
- 195,
551
- 143,
552
- 184,
553
- 101,
554
- 72,
555
- 38,
556
- 200,
557
- 18,
558
- 74,
559
- 206,
560
- 231,
561
- 210,
562
- 98,
563
- 12,
564
- 224,
565
- 31,
566
- 239,
567
- 17,
568
- 117,
569
- 120,
570
- 113,
571
- 165,
572
- 142,
573
- 118,
574
- 61,
575
- 189,
576
- 188,
577
- 134,
578
- 87,
579
- 11,
580
- 40,
581
- 47,
582
- 163,
583
- 218,
584
- 212,
585
- 228,
586
- 15,
587
- 169,
588
- 39,
589
- 83,
590
- 4,
591
- 27,
592
- 252,
593
- 172,
594
- 230,
595
- 122,
596
- 7,
597
- 174,
598
- 99,
599
- 197,
600
- 219,
601
- 226,
602
- 234,
603
- 148,
604
- 139,
605
- 196,
606
- 213,
607
- 157,
608
- 248,
609
- 144,
610
- 107,
611
- 177,
612
- 13,
613
- 214,
614
- 235,
615
- 198,
616
- 14,
617
- 207,
618
- 173,
619
- 8,
620
- 78,
621
- 215,
622
- 227,
623
- 93,
624
- 80,
625
- 30,
626
- 179,
627
- 91,
628
- 35,
629
- 56,
630
- 52,
631
- 104,
632
- 70,
633
- 3,
634
- 140,
635
- 221,
636
- 156,
637
- 125,
638
- 160,
639
- 205,
640
- 26,
641
- 65,
642
- 28
643
- ]
644
- };
645
- //#endregion
646
- //#region src/mpc/secretsharing/lagrange.ts
647
- /**
648
- * Try to interpolate a polynomial that passes through the supplied points.
649
- *
650
- * @param xs x-coordinates in the points
651
- * @param ys y-coordinates in the points
652
- * @param zero 0 element in the Finite Field.
653
- * @param one 1 element in the Finite Field.
654
- *
655
- * @returns the interpolated polynomial or null if unable to interpolate
656
- */
657
- function interpolate(xs, ys, zero, one) {
658
- if (xs.length !== ys.length) throw new Error("xs and ys must be of same size");
659
- if (xs.length === 0) throw new Error("xs and ys must have at least one element");
660
- const n = xs.length;
661
- const c = Array(n).fill(one);
662
- c[0] = one;
663
- for (let i = 0; i < n; i++) {
664
- for (let j = i; j > 0; j--) c[j] = c[j - 1].subtract(c[j].multiply(xs[i]));
665
- c[0] = c[0].multiply(xs[i].negate());
666
- }
667
- const coefficients = Array(n).fill(zero);
668
- const tc = Array(n).fill(zero);
669
- tc[n - 1] = one;
670
- for (let i = 0; i < n; i++) {
671
- let denominator = one;
672
- for (let j = 0; j < n; j++) if (i !== j) denominator = denominator.multiply(xs[i].subtract(xs[j]));
673
- const t = ys[i].multiply(denominator.modInverse());
674
- coefficients[n - 1] = coefficients[n - 1].add(t.multiply(tc[n - 1]));
675
- for (let j = n - 2; j >= 0; j--) {
676
- tc[j] = c[j + 1].add(tc[j + 1].multiply(xs[i]));
677
- coefficients[j] = coefficients[j].add(t.multiply(tc[j]));
678
- }
679
- }
680
- return Polynomial.create(coefficients, zero);
681
- }
682
- /**
683
- * Interpolate the minimal polynomial that passes through all the supplied points. And verify that
684
- * the polynomial has a degree less that maximalDegree.
685
- *
686
- * @param xs x-coordinates in the points
687
- * @param ys y-coordinates in the points
688
- * @param zero 0 element in the Finite Field.
689
- * @param one 1 element in the Finite Field.
690
- * @param maximalDegree the expected maximal degree
691
- * @return the interpolated polynomial
692
- */
693
- function interpolateCheckDegree(xs, ys, maximalDegree, zero, one) {
694
- const poly = interpolate(xs, ys, zero, one);
695
- if (poly.degree() > maximalDegree) throw new Error(`Interpolated polynomial has too high degree. Expected maximal=${maximalDegree}, actual=${poly.degree()}`);
696
- return poly;
697
- }
698
- /**
699
- * Try to interpolate a polynomial that passes through at least <code>2 &sdot; maximalDegree + 1
700
- * </code> of the supplied points.
701
- *
702
- * <p>Element lists ({@code xs} and {@code ys}) must have same size.
703
- *
704
- * @param xs x-coordinates in the points
705
- * @param ys y-coordinates in the points
706
- * @param maximalDegree the expected maximal degree
707
- * @param zero 0 element in the Finite Field.
708
- * @param one 1 element in the Finite Field.
709
- *
710
- * @returns the interpolated polynomial or undefined if unable to interpolate
711
- */
712
- function interpolateIfPossible(xs, ys, maximalDegree, zero, one) {
713
- if (xs.length !== ys.length) throw new Error("xs and ys must be of same size");
714
- return interpolateIfPossibleInner(xs, ys, maximalDegree, zero, one);
715
- }
716
- function interpolateIfPossibleInner(xs, ys, maximalDegree, zero, one) {
717
- if (xs.length <= 2 * maximalDegree + 1) {
718
- const interpolated = interpolate(xs, ys, zero, one);
719
- if (interpolated.degree() > maximalDegree) return;
720
- return interpolated;
721
- }
722
- for (let removeIndex = 0; removeIndex < xs.length; removeIndex++) {
723
- const interpolated = interpolateIfPossibleInner(withoutIndex(xs, removeIndex), withoutIndex(ys, removeIndex), maximalDegree, zero, one);
724
- if (interpolated !== void 0) return interpolated;
725
- }
726
- }
727
- function withoutIndex(values, removeIndex) {
728
- return values.filter((_value, index, _array) => index != removeIndex);
729
- }
730
- /**
731
- * Utility for lagrange interpolation.
732
- */
733
- const Lagrange = {
734
- interpolate,
735
- interpolateCheckDegree,
736
- interpolateIfPossible
737
- };
738
- //#endregion
739
- //#region src/mpc/secretsharing/shamir-secret-shares.ts
740
- /** Factory for creating elements of {@link ShamirSecretShares}. */
741
- var ShamirFactory = class {
742
- shamirConfig;
743
- /**
744
- * Create the {@link ShamirFactory}.
745
- *
746
- * @param shamirConfig configuration for creating and reconstructing shamir secret shares.
747
- */
748
- constructor(shamirConfig) {
749
- this.shamirConfig = shamirConfig;
750
- }
751
- fromPlainText(numNodes, plainText) {
752
- if (numNodes != this.shamirConfig.numNodes) throw new Error(`This shamir factory expects there to be ${this.shamirConfig.numNodes} nodes, but there was ${numNodes}.`);
753
- const randomElements = randomBytes(plainText.length * this.shamirConfig.numMalicious);
754
- const alphas = F256.alphas(this.shamirConfig.numNodes);
755
- const shares = Array.from({ length: this.shamirConfig.numNodes }, () => []);
756
- for (let i = 0; i < plainText.length; i++) {
757
- const coefficients = [F256.createElement(plainText[i])];
758
- for (let j = 0; j < this.shamirConfig.numMalicious; j++) coefficients.push(F256.createElement(randomElements[this.shamirConfig.numMalicious * i + j]));
759
- const poly = F256.createPoly(coefficients);
760
- for (let j = 0; j < this.shamirConfig.numNodes; j++) shares[j].push(poly.evaluate(alphas[j]));
761
- }
762
- return new ShamirSecretShares(this.shamirConfig, shares);
763
- }
764
- fromSharesBytes(shares) {
765
- const elementShares = shares.map((bytes) => {
766
- if (bytes == void 0) return;
767
- const elements = [];
768
- for (let i = 0; i < bytes.length; i++) elements.push(F256.createElement(bytes[i]));
769
- return elements;
770
- });
771
- return new ShamirSecretShares(this.shamirConfig, elementShares);
772
- }
773
- };
774
- /**
775
- * Secure secret-sharing scheme based on shamir-secret sharing.
776
- *
777
- * <p>Supported number of shares ({@code N}): {@code 4}
778
- *
779
- * <p>Based on the java implementation of the secret-sharing client.
780
- *
781
- * @see <a href="https://en.wikipedia.org/wiki/Shamir%27s_secret_sharing">Shamir's secret sharing,
782
- * Wikipedia</a>
783
- */
784
- var ShamirSecretShares = class {
785
- shares;
786
- shamirConfig;
787
- constructor(shamirConfig, shares) {
788
- if (shares.length != shamirConfig.numNodes) throw new Error(`There must be ${shamirConfig.numNodes} nodes`);
789
- const numReceivedShares = shares.filter((s) => s != void 0).length;
790
- if (numReceivedShares < shamirConfig.numToReconstruct) throw new Error(`Must have received at least ${shamirConfig.numToReconstruct} shares to reconstruct. Received ${numReceivedShares}.`);
791
- this.shamirConfig = shamirConfig;
792
- this.shares = shares;
793
- }
794
- getShareBytes(nodeIndex) {
795
- const share = this.shares[nodeIndex];
796
- if (share == void 0) throw new Error("Expected share to be defined");
797
- return Buffer.from(share.map((field) => field.value));
798
- }
799
- numShares() {
800
- return this.shamirConfig.numNodes;
801
- }
802
- reconstructPlainText() {
803
- const alphas = F256.alphas(this.shamirConfig.numNodes);
804
- const definedAlphas = [];
805
- const definedShares = [];
806
- for (let i = 0; i < this.shares.length; i++) {
807
- const share = this.shares[i];
808
- if (share != void 0) {
809
- definedAlphas.push(alphas[i]);
810
- definedShares.push(share);
811
- }
812
- }
813
- const reconstructedElements = [];
814
- const numElements = definedShares[0].length;
815
- for (let i = 0; i < numElements; i++) {
816
- const sharesOfIthElement = [];
817
- for (let j = 0; j < definedShares.length; j++) sharesOfIthElement.push(definedShares[j][i]);
818
- const interpolated = Lagrange.interpolateIfPossible(definedAlphas, sharesOfIthElement, this.shamirConfig.numMalicious, F256.ZERO, F256.ONE);
819
- if (interpolated === void 0) throw new Error("Unable to reconstruct secret");
820
- reconstructedElements.push(interpolated.getConstantTerm().value);
821
- }
822
- return Buffer.from(reconstructedElements);
823
- }
824
- static FACTORY = new ShamirFactory({
825
- numMalicious: 1,
826
- numNodes: 4,
827
- numToReconstruct: 2
828
- });
829
- };
830
- function getRandomBytes(length) {
831
- const array = new Uint8Array(length);
832
- crypto.getRandomValues(array);
833
- return Buffer.from(array);
834
- }
835
- //#endregion
836
- //#region src/mpc/types.ts
837
- const UPLOAD_TYPES = { UploadSignatureMessage: [{
838
- name: "share_commitments",
839
- type: "bytes32[]"
840
- }, {
841
- name: "recovering_addresses",
842
- type: "string[]"
843
- }] };
844
- const DOWNLOAD_TYPES = { DownloadSignatureMessage: [
845
- {
846
- name: "recovering_address",
847
- type: "string"
848
- },
849
- {
850
- name: "timestamp",
851
- type: "uint64"
852
- },
853
- {
854
- name: "public_key",
855
- type: "bytes32"
856
- }
857
- ] };
858
- const UPDATE_TYPES = { UpdateWalletsSignatureMessage: [{
859
- name: "recovering_addresses",
860
- type: "string[]"
861
- }, {
862
- name: "timestamp",
863
- type: "uint64"
864
- }] };
865
- const ADD_ADDRESS_TYPES = { AddAddressSignatureMessage: [
866
- {
867
- name: "recovering_address",
868
- type: "string"
869
- },
870
- {
871
- name: "address_to_add",
872
- type: "string"
873
- },
874
- {
875
- name: "timestamp",
876
- type: "uint64"
877
- }
878
- ] };
879
- const REMOVE_ADDRESS_TYPES = { RemoveAddressSignatureMessage: [
880
- {
881
- name: "recovering_address",
882
- type: "string"
883
- },
884
- {
885
- name: "address_to_remove",
886
- type: "string"
887
- },
888
- {
889
- name: "timestamp",
890
- type: "uint64"
891
- }
892
- ] };
893
- //#endregion
894
- //#region src/mpc/client.ts
895
- var Client = class Client {
896
- baseUrl;
897
- contractAddress;
898
- engines;
899
- walletType;
900
- signerAddress;
901
- signerPublicKey;
902
- factory;
903
- numNodes;
904
- constructor(baseUrl, contractAddress, numMalicious, numNodes, numToReconstruct, walletType, signerAddress, signerPublicKey) {
905
- this.baseUrl = baseUrl;
906
- this.contractAddress = contractAddress;
907
- this.reconfigure(walletType, signerAddress, signerPublicKey);
908
- this.numNodes = numNodes;
909
- this.factory = new ShamirFactory({
910
- numMalicious,
911
- numNodes,
912
- numToReconstruct
913
- });
914
- }
915
- reconfigure(walletType, signerAddress, signerPublicKey) {
916
- if ([
917
- "evm",
918
- "xrpl",
919
- "near",
920
- "facesign",
921
- "stellar"
922
- ].includes(walletType)) {
923
- console.warn("Deprecated wallet type", walletType, ", please upgrade to latest SDK version");
924
- switch (walletType) {
925
- case "evm":
926
- walletType = "EVM";
927
- break;
928
- case "xrpl":
929
- walletType = "XRPL";
930
- break;
931
- case "near":
932
- walletType = "NEAR";
933
- break;
934
- case "stellar":
935
- walletType = "Stellar";
936
- break;
937
- case "facesign":
938
- walletType = "FaceSign";
939
- break;
940
- }
941
- }
942
- invariant(WALLET_TYPES.includes(walletType), `Invalid signer type: ${walletType}`);
943
- invariant([
944
- "XRPL",
945
- "NEAR",
946
- "FaceSign"
947
- ].includes(walletType) && signerPublicKey || walletType === "EVM", "Signer public key is required for XRPL, NEAR and FaceSign");
948
- this.walletType = walletType;
949
- this.engines = void 0;
950
- this.signerAddress = signerAddress;
951
- if (signerPublicKey) this.signerPublicKey = signerPublicKey;
952
- }
953
- async uploadSecret(id, uploadSignature, signature, blindedShares) {
954
- const engineClients = await this.getEngines();
955
- const promises = [];
956
- for (let i = 0; i < engineClients.length; i++) {
957
- const engineClient = engineClients[i];
958
- const uploadRequest = {
959
- ...uploadSignature,
960
- share_data: ethers.hexlify(blindedShares[i])
961
- };
962
- promises.push(engineClient.sendUpload(id, uploadRequest, signature));
963
- }
964
- const statuses = await Promise.all(promises);
965
- if (statuses.every((item) => item === "201")) return { status: "success" };
966
- if (statuses.filter((item) => item === "201").length > 0) return { status: "partial-success" };
967
- return { status: "failure" };
968
- }
969
- getBlindedShares(secret) {
970
- const secretShares = this.factory.fromPlainText(this.numNodes, secret);
971
- var blindedShares = [];
972
- for (let i = 0; i < secretShares.numShares(); i++) blindedShares.push(Client.blindShare(secretShares.getShareBytes(i)));
973
- return blindedShares;
974
- }
975
- uploadMessageToSign(uploadRequest) {
976
- return {
977
- domain: this.getTypedDomain(),
978
- types: UPLOAD_TYPES,
979
- value: uploadRequest
980
- };
981
- }
982
- uploadRequest(blindedShares) {
983
- console.log({
984
- mpc: "uploading to MPC",
985
- walletType: this.walletType,
986
- address: this.signerAddress,
987
- publicKey: this.signerPublicKey
988
- });
989
- var address = "";
990
- switch (this.walletType) {
991
- case "EVM":
992
- address = `eip712:${this.signerAddress}`;
993
- break;
994
- case "XRPL":
995
- address = `XRPL:${this.signerPublicKey}`;
996
- break;
997
- case "NEAR":
998
- address = `NEAR:${this.signerPublicKey?.replace("ed25519:", "")}`;
999
- break;
1000
- case "FaceSign":
1001
- address = `FACESIGN:${this.signerPublicKey}`;
1002
- break;
1003
- default: throw new Error("Invalid signer type");
1004
- }
1005
- return {
1006
- share_commitments: blindedShares.map((b) => ethers.keccak256(b)),
1007
- recovering_addresses: [address]
1008
- };
1009
- }
1010
- downloadMessageToSign(downloadRequest) {
1011
- return {
1012
- domain: this.getTypedDomain(),
1013
- types: DOWNLOAD_TYPES,
1014
- value: downloadRequest
1015
- };
1016
- }
1017
- downloadRequest(publicKey) {
1018
- var address = "";
1019
- switch (this.walletType) {
1020
- case "EVM":
1021
- address = `eip712:${this.signerAddress}`;
1022
- break;
1023
- case "XRPL":
1024
- address = `XRPL:${this.signerPublicKey}`;
1025
- break;
1026
- case "NEAR":
1027
- address = `NEAR:${this.signerPublicKey?.replace("ed25519:", "")}`;
1028
- break;
1029
- case "FaceSign":
1030
- address = `FACESIGN:${this.signerPublicKey}`;
1031
- break;
1032
- default: throw new Error("Invalid signer type");
1033
- }
1034
- return {
1035
- recovering_address: address,
1036
- timestamp: Date.now(),
1037
- public_key: ethers.hexlify(publicKey)
1038
- };
1039
- }
1040
- async downloadSecret(id, downloadRequest, signature, secretKey) {
1041
- const shares = [];
1042
- const engineClients = await this.getEngines();
1043
- for (let i = 0; i < engineClients.length; i++) {
1044
- const engineClient = engineClients[i];
1045
- shares.push(engineClient.downloadAndDecrypt(id, downloadRequest, signature, secretKey));
1046
- }
1047
- const secretShares = await Promise.all(shares);
1048
- console.log({ secretSharesDownloadStatuses: secretShares.map((item) => item.status) });
1049
- if (secretShares.every((item) => item.status === "404")) return {
1050
- status: "not-stored",
1051
- secret: void 0
1052
- };
1053
- var secret;
1054
- try {
1055
- secret = this.factory.fromSharesBytes(secretShares.map((item) => item.share)).reconstructPlainText();
1056
- return {
1057
- status: "ok",
1058
- secret
1059
- };
1060
- } catch (_e) {
1061
- return {
1062
- status: "error",
1063
- secret: void 0
1064
- };
1065
- }
1066
- }
1067
- addAddressMessageToSign(addressToAdd, publicKey, addressToAddType) {
1068
- var address = "";
1069
- switch (this.walletType) {
1070
- case "EVM":
1071
- address = `eip712:${this.signerAddress}`;
1072
- break;
1073
- case "XRPL":
1074
- address = `XRPL:${this.signerPublicKey}`;
1075
- break;
1076
- case "NEAR":
1077
- address = `NEAR:${this.signerPublicKey?.replace("ed25519:", "")}`;
1078
- break;
1079
- case "FaceSign":
1080
- address = `FACESIGN:${this.signerPublicKey}`;
1081
- break;
1082
- default: throw new Error("Invalid signer type");
1083
- }
1084
- var addressToAddFormatted = "";
1085
- switch (addressToAddType.toLowerCase()) {
1086
- case "evm":
1087
- addressToAddFormatted = `eip712:${addressToAdd}`;
1088
- break;
1089
- case "xrpl":
1090
- addressToAddFormatted = `XRPL:${publicKey}`;
1091
- break;
1092
- case "near":
1093
- addressToAddFormatted = `NEAR:${publicKey?.replace("ed25519:", "")}`;
1094
- break;
1095
- case "facesign":
1096
- addressToAddFormatted = `FACESIGN:${publicKey}`;
1097
- break;
1098
- default: throw new Error("Invalid address to add type");
1099
- }
1100
- const value = {
1101
- recovering_address: address,
1102
- address_to_add: addressToAddFormatted,
1103
- timestamp: Date.now()
1104
- };
1105
- return {
1106
- domain: this.getTypedDomain(),
1107
- types: ADD_ADDRESS_TYPES,
1108
- value
1109
- };
1110
- }
1111
- removeAddressMessageToSign(addressToRemove, publicKey, addressToRemoveType) {
1112
- var address = "";
1113
- switch (this.walletType) {
1114
- case "EVM":
1115
- address = `eip712:${this.signerAddress}`;
1116
- break;
1117
- case "XRPL":
1118
- address = `XRPL:${this.signerPublicKey}`;
1119
- break;
1120
- case "NEAR":
1121
- address = `NEAR:${this.signerPublicKey?.replace("ed25519:", "")}`;
1122
- break;
1123
- case "FaceSign":
1124
- address = `FACESIGN:${this.signerPublicKey}`;
1125
- break;
1126
- default: throw new Error("Invalid signer type");
1127
- }
1128
- var addressToRemoveFormatted = "";
1129
- switch (addressToRemoveType.toLowerCase()) {
1130
- case "evm":
1131
- addressToRemoveFormatted = `eip712:${addressToRemove}`;
1132
- break;
1133
- case "xrpl":
1134
- addressToRemoveFormatted = `XRPL:${publicKey}`;
1135
- break;
1136
- case "near":
1137
- addressToRemoveFormatted = `NEAR:${publicKey?.replace("ed25519:", "")}`;
1138
- break;
1139
- case "facesign":
1140
- addressToRemoveFormatted = `FACESIGN:${publicKey}`;
1141
- break;
1142
- default: throw new Error("Invalid address to remove type");
1143
- }
1144
- const value = {
1145
- recovering_address: address,
1146
- address_to_remove: addressToRemoveFormatted,
1147
- timestamp: Date.now()
1148
- };
1149
- return {
1150
- domain: this.getTypedDomain(),
1151
- types: REMOVE_ADDRESS_TYPES,
1152
- value
1153
- };
1154
- }
1155
- async addAddress(userId, message, signature) {
1156
- const engineClients = await this.getEngines();
1157
- const promises = [];
1158
- for (let i = 0; i < engineClients.length; i++) {
1159
- const engineClient = engineClients[i];
1160
- promises.push(engineClient.sendAddAddress(userId, message, signature));
1161
- }
1162
- if ((await Promise.all(promises)).every((item) => item === "200")) return "success";
1163
- return "failure";
1164
- }
1165
- async removeAddress(userId, message, signature) {
1166
- const engineClients = await this.getEngines();
1167
- const promises = [];
1168
- for (let i = 0; i < engineClients.length; i++) {
1169
- const engineClient = engineClients[i];
1170
- promises.push(engineClient.sendRemoveAddress(userId, message, signature));
1171
- }
1172
- if ((await Promise.all(promises)).every((item) => item === "200")) return "success";
1173
- return "failure";
1174
- }
1175
- getTypedDomain() {
1176
- return {
1177
- name: "idOS secret store contract",
1178
- version: "1",
1179
- verifyingContract: `0x${this.contractAddress.substring(2)}`
1180
- };
1181
- }
1182
- async getEngines() {
1183
- if (this.engines === void 0) {
1184
- const rawState = await new ChainControllerApi(new Configuration({ basePath: this.baseUrl })).getContract({ address: this.contractAddress });
1185
- const state = deserializeState(Buffer.from(rawState.serializedContract, "base64"));
1186
- this.engines = state.nodes.map((value) => new EngineClient(value.endpoint, this.contractAddress, this.walletType));
1187
- }
1188
- return this.engines;
1189
- }
1190
- static blindShare(share) {
1191
- return Buffer.concat([getRandomBytes(32), share]);
1192
- }
1193
- };
1194
- //#endregion
1195
- export { UPDATE_TYPES as a, REMOVE_ADDRESS_TYPES as i, ADD_ADDRESS_TYPES as n, UPLOAD_TYPES as o, DOWNLOAD_TYPES as r, Client as t };
1196
-
1197
- //# sourceMappingURL=client-4H2-Ewlq.mjs.map