@arcium-hq/client 0.1.46 → 0.1.47
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -8
- package/build/index.cjs +695 -83
- package/build/index.d.ts +432 -23
- package/build/index.mjs +685 -77
- package/package.json +1 -1
package/build/index.mjs
CHANGED
|
@@ -1,14 +1,21 @@
|
|
|
1
1
|
import { blake2s } from '@noble/hashes/blake2s';
|
|
2
|
-
import { randomBytes, createHash, createCipheriv } from 'crypto';
|
|
2
|
+
import { randomBytes, createHash, createCipheriv, hkdfSync, createDecipheriv } from 'crypto';
|
|
3
3
|
import { ed25519, x25519 } from '@noble/curves/ed25519';
|
|
4
4
|
export { x25519 } from '@noble/curves/ed25519';
|
|
5
5
|
import * as anchor from '@coral-xyz/anchor';
|
|
6
6
|
import { Program } from '@coral-xyz/anchor';
|
|
7
|
-
import { shake256 } from '@noble/hashes/sha3';
|
|
7
|
+
import { shake256, sha3_512 } from '@noble/hashes/sha3';
|
|
8
8
|
import { invert } from '@noble/curves/abstract/modular';
|
|
9
|
+
import { randomBytes as randomBytes$1 } from '@noble/hashes/utils';
|
|
10
|
+
import { twistedEdwards } from '@noble/curves/abstract/edwards';
|
|
9
11
|
import { PublicKey } from '@solana/web3.js';
|
|
10
12
|
|
|
11
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Converts a bigint to an array of bits (least significant to most significant, in 2's complement representation).
|
|
15
|
+
* @param x - The bigint to convert.
|
|
16
|
+
* @param binSize - The number of bits to use in the representation.
|
|
17
|
+
* @returns An array of booleans representing the bits of x.
|
|
18
|
+
*/
|
|
12
19
|
function toBinLE(x, binSize) {
|
|
13
20
|
const res = [];
|
|
14
21
|
for (let i = 0; i < binSize; ++i) {
|
|
@@ -16,7 +23,11 @@ function toBinLE(x, binSize) {
|
|
|
16
23
|
}
|
|
17
24
|
return res;
|
|
18
25
|
}
|
|
19
|
-
|
|
26
|
+
/**
|
|
27
|
+
* Converts an array of bits (least significant to most significant, in 2's complement representation) to a bigint.
|
|
28
|
+
* @param xBin - The array of bits to convert.
|
|
29
|
+
* @returns The bigint represented by the bit array.
|
|
30
|
+
*/
|
|
20
31
|
function fromBinLE(xBin) {
|
|
21
32
|
let res = 0n;
|
|
22
33
|
for (let i = 0; i < xBin.length - 1; ++i) {
|
|
@@ -24,8 +35,14 @@ function fromBinLE(xBin) {
|
|
|
24
35
|
}
|
|
25
36
|
return res - (BigInt(xBin[xBin.length - 1]) << BigInt(xBin.length - 1));
|
|
26
37
|
}
|
|
27
|
-
|
|
28
|
-
|
|
38
|
+
/**
|
|
39
|
+
* Binary adder between x and y (assumes xBin and yBin are of the same length and large enough to represent the sum).
|
|
40
|
+
* @param xBin - The first operand as a bit array.
|
|
41
|
+
* @param yBin - The second operand as a bit array.
|
|
42
|
+
* @param carryIn - The initial carry-in value.
|
|
43
|
+
* @param binSize - The number of bits to use in the operation.
|
|
44
|
+
* @returns The sum as a bit array.
|
|
45
|
+
*/
|
|
29
46
|
function adder(xBin, yBin, carryIn, binSize) {
|
|
30
47
|
const res = [];
|
|
31
48
|
let carry = carryIn;
|
|
@@ -40,12 +57,24 @@ function adder(xBin, yBin, carryIn, binSize) {
|
|
|
40
57
|
}
|
|
41
58
|
return res;
|
|
42
59
|
}
|
|
43
|
-
|
|
60
|
+
/**
|
|
61
|
+
* Constant-time addition of two bigints, using 2's complement representation.
|
|
62
|
+
* @param x - The first operand.
|
|
63
|
+
* @param y - The second operand.
|
|
64
|
+
* @param binSize - The number of bits to use in the operation.
|
|
65
|
+
* @returns The sum as a bigint.
|
|
66
|
+
*/
|
|
44
67
|
function ctAdd(x, y, binSize) {
|
|
45
68
|
const resBin = adder(toBinLE(x, binSize), toBinLE(y, binSize), false, binSize);
|
|
46
69
|
return fromBinLE(resBin);
|
|
47
70
|
}
|
|
48
|
-
|
|
71
|
+
/**
|
|
72
|
+
* Constant-time subtraction of two bigints, using 2's complement representation.
|
|
73
|
+
* @param x - The first operand.
|
|
74
|
+
* @param y - The second operand.
|
|
75
|
+
* @param binSize - The number of bits to use in the operation.
|
|
76
|
+
* @returns The difference as a bigint.
|
|
77
|
+
*/
|
|
49
78
|
function ctSub(x, y, binSize) {
|
|
50
79
|
const yBin = toBinLE(y, binSize);
|
|
51
80
|
const yBinNot = [];
|
|
@@ -55,23 +84,44 @@ function ctSub(x, y, binSize) {
|
|
|
55
84
|
const resBin = adder(toBinLE(x, binSize), yBinNot, true, binSize);
|
|
56
85
|
return fromBinLE(resBin);
|
|
57
86
|
}
|
|
58
|
-
|
|
87
|
+
/**
|
|
88
|
+
* Returns the sign bit of a bigint in constant time.
|
|
89
|
+
* @param x - The bigint to check.
|
|
90
|
+
* @param binSize - The bit position to check (typically the highest bit).
|
|
91
|
+
* @returns True if the sign bit is set, false otherwise.
|
|
92
|
+
*/
|
|
59
93
|
function ctSignBit(x, binSize) {
|
|
60
94
|
return ((x >> binSize) & 1n) === 1n;
|
|
61
95
|
}
|
|
62
|
-
|
|
96
|
+
/**
|
|
97
|
+
* Constant-time less-than comparison for two bigints.
|
|
98
|
+
* @param x - The first operand.
|
|
99
|
+
* @param y - The second operand.
|
|
100
|
+
* @param binSize - The number of bits to use in the operation.
|
|
101
|
+
* @returns True if x < y, false otherwise.
|
|
102
|
+
*/
|
|
63
103
|
function ctLt(x, y, binSize) {
|
|
64
104
|
return ctSignBit(ctSub(x, y, binSize), binSize);
|
|
65
105
|
}
|
|
66
|
-
|
|
106
|
+
/**
|
|
107
|
+
* Constant-time select between two bigints based on a boolean condition.
|
|
108
|
+
* @param b - The condition; if true, select x, otherwise select y.
|
|
109
|
+
* @param x - The value to select if b is true.
|
|
110
|
+
* @param y - The value to select if b is false.
|
|
111
|
+
* @param binSize - The number of bits to use in the operation.
|
|
112
|
+
* @returns The selected bigint.
|
|
113
|
+
*/
|
|
67
114
|
function ctSelect(b, x, y, binSize) {
|
|
68
115
|
return ctAdd(y, BigInt(b) * (ctSub(x, y, binSize)), binSize);
|
|
69
116
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
117
|
+
/**
|
|
118
|
+
* Checks if a bigint fits in the range -2^binSize <= x < 2^binSize.
|
|
119
|
+
* Not constant-time for arbitrary x, but is constant-time for all inputs for which the function returns true.
|
|
120
|
+
* If you assert your inputs satisfy verifyBinSize(x, binSize), you need not care about the non constant-timeness of this function.
|
|
121
|
+
* @param x - The bigint to check.
|
|
122
|
+
* @param binSize - The number of bits to use in the check.
|
|
123
|
+
* @returns True if x fits in the range, false otherwise.
|
|
124
|
+
*/
|
|
75
125
|
function verifyBinSize(x, binSize) {
|
|
76
126
|
const bin = (x >> binSize).toString(2);
|
|
77
127
|
return bin === '0' || bin === '-1';
|
|
@@ -259,10 +309,17 @@ function randMatrix(field, nrows, ncols) {
|
|
|
259
309
|
return new Matrix(field, data);
|
|
260
310
|
}
|
|
261
311
|
|
|
312
|
+
/**
|
|
313
|
+
* Curve25519 base field as an IField instance.
|
|
314
|
+
*/
|
|
262
315
|
const CURVE25519_BASE_FIELD = ed25519.CURVE.Fp;
|
|
263
316
|
// hardcode security level to 128 bits
|
|
264
317
|
const SECURITY_LEVEL = 128;
|
|
265
318
|
// We refer to https://tosc.iacr.org/index.php/ToSC/article/view/8695/8287 for more details.
|
|
319
|
+
/**
|
|
320
|
+
* Description and parameters for the Rescue cipher or hash function, including round constants, MDS matrix, and key schedule.
|
|
321
|
+
* See: https://tosc.iacr.org/index.php/ToSC/article/view/8695/8287
|
|
322
|
+
*/
|
|
266
323
|
class RescueDesc {
|
|
267
324
|
mode;
|
|
268
325
|
field;
|
|
@@ -278,6 +335,12 @@ class RescueDesc {
|
|
|
278
335
|
mdsMatInverse;
|
|
279
336
|
// The round keys, needed for encryption and decryption.
|
|
280
337
|
roundKeys;
|
|
338
|
+
/**
|
|
339
|
+
* Constructs a RescueDesc for a given field and mode (cipher or hash).
|
|
340
|
+
* Initializes round constants, MDS matrix, and key schedule.
|
|
341
|
+
* @param field - The field to use (e.g., CURVE25519_BASE_FIELD).
|
|
342
|
+
* @param mode - The mode: block cipher or hash function.
|
|
343
|
+
*/
|
|
281
344
|
constructor(field, mode) {
|
|
282
345
|
this.field = field;
|
|
283
346
|
this.mode = mode;
|
|
@@ -323,6 +386,11 @@ class RescueDesc {
|
|
|
323
386
|
}
|
|
324
387
|
}
|
|
325
388
|
}
|
|
389
|
+
/**
|
|
390
|
+
* Samples round constants for the Rescue permutation, using SHAKE256.
|
|
391
|
+
* @param nRounds - The number of rounds.
|
|
392
|
+
* @returns An array of round constant matrices.
|
|
393
|
+
*/
|
|
326
394
|
sampleConstants(nRounds) {
|
|
327
395
|
const field = this.field;
|
|
328
396
|
const m = this.m;
|
|
@@ -396,9 +464,19 @@ class RescueDesc {
|
|
|
396
464
|
default: return [];
|
|
397
465
|
}
|
|
398
466
|
}
|
|
467
|
+
/**
|
|
468
|
+
* Applies the Rescue permutation to a state matrix.
|
|
469
|
+
* @param state - The input state matrix.
|
|
470
|
+
* @returns The permuted state matrix.
|
|
471
|
+
*/
|
|
399
472
|
permute(state) {
|
|
400
473
|
return rescuePermutation(this.mode, this.alpha, this.alphaInverse, this.mdsMat, this.roundKeys, state)[2 * this.nRounds];
|
|
401
474
|
}
|
|
475
|
+
/**
|
|
476
|
+
* Applies the inverse Rescue permutation to a state matrix.
|
|
477
|
+
* @param state - The input state matrix.
|
|
478
|
+
* @returns The inverse-permuted state matrix.
|
|
479
|
+
*/
|
|
402
480
|
permuteInverse(state) {
|
|
403
481
|
return rescuePermutationInverse(this.mode, this.alpha, this.alphaInverse, this.mdsMatInverse, this.roundKeys, state)[2 * this.nRounds];
|
|
404
482
|
}
|
|
@@ -570,7 +648,17 @@ function toVec(data) {
|
|
|
570
648
|
return dataVec;
|
|
571
649
|
}
|
|
572
650
|
|
|
651
|
+
/**
|
|
652
|
+
* Number of mantissa bits for double-precision floating point values.
|
|
653
|
+
*/
|
|
573
654
|
const DOUBLE_PRECISION_MANTISSA = 52;
|
|
655
|
+
/**
|
|
656
|
+
* Encodes a value as a bigint suitable for Rescue encryption, handling booleans, bigints, and numbers.
|
|
657
|
+
* The encoding is performed in constant-time to avoid leaking information through timing side-channels.
|
|
658
|
+
* Throws if the value is out of the supported range for the field.
|
|
659
|
+
* @param v - The value to encode (MScalar, MFloat, or MBoolean).
|
|
660
|
+
* @returns The encoded value as a bigint.
|
|
661
|
+
*/
|
|
574
662
|
function encodeAsRescueEncryptable(v) {
|
|
575
663
|
if (typeof v === 'boolean') {
|
|
576
664
|
return v ? 1n : 0n;
|
|
@@ -599,6 +687,13 @@ function encodeAsRescueEncryptable(v) {
|
|
|
599
687
|
// but typescript kept thinking ixInput: readonly null[] and I can't figure out why, so we do this hack
|
|
600
688
|
// for now.
|
|
601
689
|
// TODO: Revisit and fix the types correctly.
|
|
690
|
+
/**
|
|
691
|
+
* Secret-shares the inputs for a confidential instruction, encoding each value as needed and splitting it for each node's public key.
|
|
692
|
+
* @param ixInput - The array of input values to secret-share.
|
|
693
|
+
* @param nodeX25519Keys - The array of node X25519 public keys to share with.
|
|
694
|
+
* @returns A 2D array of SecretShare objects, one array per input value.
|
|
695
|
+
* @throws Error if an input type cannot be parsed.
|
|
696
|
+
*/
|
|
602
697
|
function secretShareInputs(ixInput, nodeX25519Keys) {
|
|
603
698
|
const shares = [];
|
|
604
699
|
// Need to explicitly tell typescript input can be any of these, else it only thinks {} is possible
|
|
@@ -650,9 +745,16 @@ function getBinSize(max) {
|
|
|
650
745
|
return BigInt(Math.floor(Math.log2(Number(max)))) + 3n;
|
|
651
746
|
}
|
|
652
747
|
|
|
653
|
-
|
|
748
|
+
/**
|
|
749
|
+
* Scalar field prime modulus for Curve25519: 2^252 + 27742317777372353535851937790883648493
|
|
750
|
+
*/
|
|
654
751
|
const CURVE25519_SCALAR_FIELD_MODULUS = ed25519.CURVE.n;
|
|
655
|
-
|
|
752
|
+
/**
|
|
753
|
+
* Encrypts a value into the format expected by the DA layer, using secret sharing and encryption for each node's public key.
|
|
754
|
+
* @param val - The value to secret-share and encrypt.
|
|
755
|
+
* @param nodeX25519Keys - The array of node X25519 public keys.
|
|
756
|
+
* @returns An array of SecretShare objects, one for each node.
|
|
757
|
+
*/
|
|
656
758
|
function secretShareValue(val, nodeX25519Keys) {
|
|
657
759
|
const rawShares = genRawShares(val, nodeX25519Keys.length, CURVE25519_SCALAR_FIELD_MODULUS);
|
|
658
760
|
return zip(rawShares, nodeX25519Keys).map(([share, key]) => encryptForDA(key, share, CURVE25519_SCALAR_FIELD_MODULUS));
|
|
@@ -671,10 +773,10 @@ function newSecretShare(ciphertext, nonce, ephemeralPublicKey) {
|
|
|
671
773
|
}
|
|
672
774
|
/**
|
|
673
775
|
* Generates secret shares for a given value in the Curve25519 field.
|
|
674
|
-
* @param secret The secret value to be shared (as a BigInt)
|
|
675
|
-
* @param n The number of shares to generate
|
|
676
|
-
* @param mod The modulo of the field over which to generate shares
|
|
677
|
-
* @returns An array of n secret shares
|
|
776
|
+
* @param secret - The secret value to be shared (as a BigInt).
|
|
777
|
+
* @param n - The number of shares to generate.
|
|
778
|
+
* @param mod - The modulo of the field over which to generate shares (default: CURVE25519_SCALAR_FIELD_MODULUS).
|
|
779
|
+
* @returns An array of n secret shares as bigints.
|
|
678
780
|
*/
|
|
679
781
|
function genRawShares(secret, n, mod = CURVE25519_SCALAR_FIELD_MODULUS) {
|
|
680
782
|
const shares = [];
|
|
@@ -690,11 +792,11 @@ function genRawShares(secret, n, mod = CURVE25519_SCALAR_FIELD_MODULUS) {
|
|
|
690
792
|
}
|
|
691
793
|
/// ENCRYPTION
|
|
692
794
|
/**
|
|
693
|
-
* Encrypts a field element for the DA layer.
|
|
694
|
-
* @param publicKey The recipient's x25519 public key
|
|
695
|
-
* @param valueToEncrypt The bigint value to encrypt
|
|
696
|
-
* @param modulo Bound on the value
|
|
697
|
-
* @returns An object containing the ciphertext and ephemeral public key.
|
|
795
|
+
* Encrypts a field element for the DA layer using the recipient's x25519 public key.
|
|
796
|
+
* @param publicKey - The recipient's x25519 public key.
|
|
797
|
+
* @param valueToEncrypt - The bigint value to encrypt.
|
|
798
|
+
* @param modulo - Bound on the value (default: CURVE25519_SCALAR_FIELD_MODULUS).
|
|
799
|
+
* @returns An object containing the ciphertext, nonce, and ephemeral public key.
|
|
698
800
|
*/
|
|
699
801
|
function encryptForDA(publicKey, valueToEncrypt, modulo = CURVE25519_SCALAR_FIELD_MODULUS) {
|
|
700
802
|
// Check if the value to encrypt is smaller than the modulo
|
|
@@ -710,6 +812,12 @@ function encryptForDA(publicKey, valueToEncrypt, modulo = CURVE25519_SCALAR_FIEL
|
|
|
710
812
|
const { ciphertext, nonce } = aesCtrEncrypt(valueToEncrypt, sharedSecret);
|
|
711
813
|
return newSecretShare(ciphertext, nonce, ephemeralPublicKey);
|
|
712
814
|
}
|
|
815
|
+
/**
|
|
816
|
+
* Computes a shared encryption key using ECDH (x25519) and hashes it with blake2s.
|
|
817
|
+
* @param privKey - The private key as a Uint8Array.
|
|
818
|
+
* @param pubKey - The public key as a Uint8Array.
|
|
819
|
+
* @returns The derived encryption key as a Uint8Array.
|
|
820
|
+
*/
|
|
713
821
|
function getEncryptionKey(privKey, pubKey) {
|
|
714
822
|
const sharedSecret = x25519.getSharedSecret(privKey, pubKey);
|
|
715
823
|
return blake2s(sharedSecret);
|
|
@@ -743,9 +851,10 @@ function aesCtrEncrypt(val, key) {
|
|
|
743
851
|
}
|
|
744
852
|
/// HELPERS
|
|
745
853
|
/**
|
|
746
|
-
* Generates a random
|
|
854
|
+
* Generates a random value within the field bound by q.
|
|
855
|
+
* @param q - The upper bound (exclusive) for the random value.
|
|
747
856
|
* @returns A random bigint value between 0 and q-1.
|
|
748
|
-
*/
|
|
857
|
+
*/
|
|
749
858
|
function generateRandomFieldElem(q) {
|
|
750
859
|
const byteLength = (q.toString(2).length + 7) >> 3;
|
|
751
860
|
let r;
|
|
@@ -755,10 +864,22 @@ function generateRandomFieldElem(q) {
|
|
|
755
864
|
} while (r >= q);
|
|
756
865
|
return r;
|
|
757
866
|
}
|
|
758
|
-
|
|
867
|
+
/**
|
|
868
|
+
* Computes the positive modulo of a over m.
|
|
869
|
+
* @param a - The dividend.
|
|
870
|
+
* @param m - The modulus.
|
|
871
|
+
* @returns The positive remainder of a mod m.
|
|
872
|
+
*/
|
|
759
873
|
function positiveModulo(a, m) {
|
|
760
874
|
return ((a % m) + m) % m;
|
|
761
875
|
}
|
|
876
|
+
/**
|
|
877
|
+
* Serializes a bigint to a little-endian Uint8Array of the specified length.
|
|
878
|
+
* @param val - The bigint value to serialize.
|
|
879
|
+
* @param lengthInBytes - The desired length of the output array.
|
|
880
|
+
* @returns The serialized value as a Uint8Array.
|
|
881
|
+
* @throws Error if the value is too large for the specified length.
|
|
882
|
+
*/
|
|
762
883
|
function serializeLE(val, lengthInBytes) {
|
|
763
884
|
const result = new Uint8Array(lengthInBytes);
|
|
764
885
|
let tempVal = val;
|
|
@@ -771,6 +892,11 @@ function serializeLE(val, lengthInBytes) {
|
|
|
771
892
|
}
|
|
772
893
|
return result;
|
|
773
894
|
}
|
|
895
|
+
/**
|
|
896
|
+
* Deserializes a little-endian Uint8Array to a bigint.
|
|
897
|
+
* @param bytes - The Uint8Array to deserialize.
|
|
898
|
+
* @returns The deserialized bigint value.
|
|
899
|
+
*/
|
|
774
900
|
function deserializeLE(bytes) {
|
|
775
901
|
let result = BigInt(0);
|
|
776
902
|
for (let i = 0; i < bytes.length; i++) {
|
|
@@ -779,6 +905,11 @@ function deserializeLE(bytes) {
|
|
|
779
905
|
return result;
|
|
780
906
|
}
|
|
781
907
|
// GENERAL
|
|
908
|
+
/**
|
|
909
|
+
* Computes the SHA-256 hash of an array of Uint8Arrays.
|
|
910
|
+
* @param byteArrays - The arrays to hash.
|
|
911
|
+
* @returns The SHA-256 hash as a Buffer.
|
|
912
|
+
*/
|
|
782
913
|
function sha256(byteArrays) {
|
|
783
914
|
const hash = createHash('sha256');
|
|
784
915
|
byteArrays.forEach((byteArray) => {
|
|
@@ -787,19 +918,28 @@ function sha256(byteArrays) {
|
|
|
787
918
|
return hash.digest();
|
|
788
919
|
}
|
|
789
920
|
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
921
|
+
/**
|
|
922
|
+
* The Rescue-Prime hash function, as described in https://eprint.iacr.org/2020/1143.pdf.
|
|
923
|
+
* Used with fixed m = 6 and capacity = 1 (rate = 5). According to Section 2.2, this offers log2(CURVE25519_BASE_FIELD.ORDER) / 2 bits of security against collision, preimage, and second-preimage attacks.
|
|
924
|
+
* See the referenced paper for further details.
|
|
925
|
+
*/
|
|
794
926
|
class RescuePrimeHash {
|
|
795
927
|
desc;
|
|
796
928
|
rate;
|
|
929
|
+
/**
|
|
930
|
+
* Constructs a RescuePrimeHash instance with m = 6 and capacity = 1.
|
|
931
|
+
*/
|
|
797
932
|
constructor() {
|
|
798
933
|
this.desc = new RescueDesc(CURVE25519_BASE_FIELD, { kind: 'hash', m: 6, capacity: 1 });
|
|
799
934
|
this.rate = 6 - 1;
|
|
800
935
|
}
|
|
801
936
|
// This is Algorithm 1 from https://eprint.iacr.org/2020/1143.pdf, though with the padding (see Algorithm 2).
|
|
802
937
|
// The hash function outputs this.rate elements.
|
|
938
|
+
/**
|
|
939
|
+
* Computes the Rescue-Prime hash of a message, with padding as described in Algorithm 2 of the paper.
|
|
940
|
+
* @param message - The input message as an array of bigints.
|
|
941
|
+
* @returns The hash output as an array of bigints (length = rate).
|
|
942
|
+
*/
|
|
803
943
|
digest(message) {
|
|
804
944
|
message.push(1n);
|
|
805
945
|
while (message.length % this.rate !== 0) {
|
|
@@ -829,21 +969,33 @@ class RescuePrimeHash {
|
|
|
829
969
|
}
|
|
830
970
|
}
|
|
831
971
|
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
972
|
+
/**
|
|
973
|
+
* HMACRescuePrime provides a message authentication code (MAC) using the Rescue-Prime hash function.
|
|
974
|
+
* Rescue-Prime is based on the sponge construction, which allows the use of a simpler MAC in place of the traditional HMAC.
|
|
975
|
+
* For more details and explanations, see: https://keccak.team/files/SpongeFunctions.pdf (Appendix B) or https://keccak.team/keccak_strengths.html.
|
|
976
|
+
*/
|
|
836
977
|
class HMACRescuePrime {
|
|
837
978
|
hasher;
|
|
979
|
+
/**
|
|
980
|
+
* Constructs a new HMACRescuePrime instance.
|
|
981
|
+
*/
|
|
838
982
|
constructor() {
|
|
839
983
|
this.hasher = new RescuePrimeHash();
|
|
840
984
|
}
|
|
985
|
+
/**
|
|
986
|
+
* Computes the HMAC (or MAC) digest of a message with a given key using Rescue-Prime.
|
|
987
|
+
* The key is padded to the hash function's rate, then concatenated with the message.
|
|
988
|
+
* @param key - The key as an array of bigints.
|
|
989
|
+
* @param message - The message as an array of bigints.
|
|
990
|
+
* @returns The MAC digest as an array of bigints.
|
|
991
|
+
* @throws Error if the key is longer than the hash function's rate.
|
|
992
|
+
*/
|
|
841
993
|
digest(key, message) {
|
|
842
994
|
// HMAC-digest(key, message) = hasher.digest(key || message), since Rescue-Prime is based on
|
|
843
995
|
// the sponge construction.
|
|
844
996
|
// We follow https://datatracker.ietf.org/doc/html/rfc2104, though since Rescue-Prime is not based
|
|
845
997
|
// on the Merkle-Damgard construction we cannot have an exact anology between the
|
|
846
|
-
// parameters. For our purpose, we set B = L = hasher.rate
|
|
998
|
+
// parameters. For our purpose, we set B = L = hasher.rate.
|
|
847
999
|
if (key.length > this.hasher.rate) {
|
|
848
1000
|
throw Error(`length of key is supposed to be at most the hash function's rate (found ${key.length} and ${this.hasher.rate})`);
|
|
849
1001
|
}
|
|
@@ -856,39 +1008,82 @@ class HMACRescuePrime {
|
|
|
856
1008
|
}
|
|
857
1009
|
}
|
|
858
1010
|
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
1011
|
+
/**
|
|
1012
|
+
* HKDF (HMAC-based Extract-and-Expand Key Derivation Function) using the Rescue-Prime hash function.
|
|
1013
|
+
* Follows RFC 5869. Only supports L = HashLen.
|
|
1014
|
+
*/
|
|
863
1015
|
class HKDFRescuePrime {
|
|
864
1016
|
hmac;
|
|
1017
|
+
/**
|
|
1018
|
+
* Constructs a new HKDFRescuePrime instance.
|
|
1019
|
+
*/
|
|
865
1020
|
constructor() {
|
|
866
1021
|
this.hmac = new HMACRescuePrime();
|
|
867
1022
|
}
|
|
1023
|
+
/**
|
|
1024
|
+
* HKDF-Extract step: derives a pseudorandom key (PRK) from the input keying material (IKM) and salt.
|
|
1025
|
+
* @param salt - The salt value as an array of bigints.
|
|
1026
|
+
* @param ikm - The input keying material as an array of bigints.
|
|
1027
|
+
* @returns The pseudorandom key (PRK) as an array of bigints.
|
|
1028
|
+
*/
|
|
868
1029
|
extract(salt, ikm) {
|
|
1030
|
+
if (salt.length === 0) {
|
|
1031
|
+
// HashLen = hasher.rate for Rescue-Prime
|
|
1032
|
+
for (let i = 0; i < this.hmac.hasher.rate; ++i) {
|
|
1033
|
+
salt.push(0n);
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
869
1036
|
return this.hmac.digest(salt, ikm);
|
|
870
1037
|
}
|
|
1038
|
+
/**
|
|
1039
|
+
* HKDF-Expand step: expands the pseudorandom key (PRK) with info to produce output keying material (OKM).
|
|
1040
|
+
* Only supports L = HashLen = 5, i.e. N = 1.
|
|
1041
|
+
* @param prk - The pseudorandom key as an array of bigints.
|
|
1042
|
+
* @param info - The context and application specific information as an array of bigints.
|
|
1043
|
+
* @returns The output keying material (OKM) as an array of bigints.
|
|
1044
|
+
*/
|
|
871
1045
|
expand(prk, info) {
|
|
872
|
-
// we
|
|
1046
|
+
// we only support L = HashLen = 5, i.e. N = 1
|
|
1047
|
+
// message = empty string | info | 0x01
|
|
873
1048
|
info.push(1n);
|
|
874
1049
|
return this.hmac.digest(prk, info);
|
|
875
1050
|
}
|
|
1051
|
+
/**
|
|
1052
|
+
* Performs the full HKDF (extract and expand) to derive output keying material (OKM).
|
|
1053
|
+
* @param salt - The salt value as an array of bigints.
|
|
1054
|
+
* @param ikm - The input keying material as an array of bigints.
|
|
1055
|
+
* @param info - The context and application specific information as an array of bigints.
|
|
1056
|
+
* @returns The output keying material (OKM) as an array of bigints.
|
|
1057
|
+
*/
|
|
876
1058
|
okm(salt, ikm, info) {
|
|
877
1059
|
const prk = this.extract(salt, ikm);
|
|
878
1060
|
return this.expand(prk, info);
|
|
879
1061
|
}
|
|
880
1062
|
}
|
|
881
1063
|
|
|
882
|
-
|
|
883
|
-
|
|
1064
|
+
/**
|
|
1065
|
+
* The Rescue cipher in Counter (CTR) mode, with a fixed block size m = 5.
|
|
1066
|
+
* See: https://tosc.iacr.org/index.php/ToSC/article/view/8695/8287
|
|
1067
|
+
*/
|
|
884
1068
|
class RescueCipher {
|
|
885
1069
|
desc;
|
|
1070
|
+
/**
|
|
1071
|
+
* Constructs a RescueCipher instance using a shared secret.
|
|
1072
|
+
* The key is derived using HKDF-RescuePrime and used to initialize the RescueDesc.
|
|
1073
|
+
* @param sharedSecret - The shared secret to derive the cipher key from.
|
|
1074
|
+
*/
|
|
886
1075
|
constructor(sharedSecret) {
|
|
887
1076
|
const hkdf = new HKDFRescuePrime();
|
|
888
|
-
const rescueKey = hkdf.okm([
|
|
1077
|
+
const rescueKey = hkdf.okm([], [deserializeLE(sharedSecret)], []);
|
|
889
1078
|
this.desc = new RescueDesc(CURVE25519_BASE_FIELD, { kind: 'cipher', key: rescueKey });
|
|
890
1079
|
}
|
|
891
|
-
|
|
1080
|
+
/**
|
|
1081
|
+
* Encrypts the plaintext vector in Counter (CTR) mode (raw, returns bigints).
|
|
1082
|
+
* @param plaintext - The array of plaintext bigints to encrypt.
|
|
1083
|
+
* @param nonce - A 16-byte nonce for CTR mode.
|
|
1084
|
+
* @returns The ciphertext as an array of bigints.
|
|
1085
|
+
* @throws Error if the nonce is not 16 bytes long.
|
|
1086
|
+
*/
|
|
892
1087
|
encrypt_raw(plaintext, nonce) {
|
|
893
1088
|
if (nonce.length !== 16) {
|
|
894
1089
|
throw Error(`nonce must be of length 16 (found ${nonce.length})`);
|
|
@@ -921,11 +1116,22 @@ class RescueCipher {
|
|
|
921
1116
|
}
|
|
922
1117
|
return ciphertext;
|
|
923
1118
|
}
|
|
924
|
-
|
|
1119
|
+
/**
|
|
1120
|
+
* Encrypts the plaintext vector in Counter (CTR) mode and serializes each block.
|
|
1121
|
+
* @param plaintext - The array of plaintext bigints to encrypt.
|
|
1122
|
+
* @param nonce - A 16-byte nonce for CTR mode.
|
|
1123
|
+
* @returns The ciphertext as an array of arrays of numbers (each 32 bytes).
|
|
1124
|
+
*/
|
|
925
1125
|
encrypt(plaintext, nonce) {
|
|
926
1126
|
return this.encrypt_raw(plaintext, nonce).map((c) => Array.from(serializeLE(c, 32)));
|
|
927
1127
|
}
|
|
928
|
-
|
|
1128
|
+
/**
|
|
1129
|
+
* Decrypts the ciphertext vector in Counter (CTR) mode (raw, expects bigints).
|
|
1130
|
+
* @param ciphertext - The array of ciphertext bigints to decrypt.
|
|
1131
|
+
* @param nonce - A 16-byte nonce for CTR mode.
|
|
1132
|
+
* @returns The decrypted plaintext as an array of bigints.
|
|
1133
|
+
* @throws Error if the nonce is not 16 bytes long.
|
|
1134
|
+
*/
|
|
929
1135
|
decrypt_raw(ciphertext, nonce) {
|
|
930
1136
|
if (nonce.length !== 16) {
|
|
931
1137
|
throw Error(`nonce must be of length 16 (found ${nonce.length})`);
|
|
@@ -955,7 +1161,12 @@ class RescueCipher {
|
|
|
955
1161
|
}
|
|
956
1162
|
return decrypted;
|
|
957
1163
|
}
|
|
958
|
-
|
|
1164
|
+
/**
|
|
1165
|
+
* Deserializes and decrypts the ciphertext vector in Counter (CTR) mode.
|
|
1166
|
+
* @param ciphertext - The array of arrays of numbers (each 32 bytes) to decrypt.
|
|
1167
|
+
* @param nonce - A 16-byte nonce for CTR mode.
|
|
1168
|
+
* @returns The decrypted plaintext as an array of bigints.
|
|
1169
|
+
*/
|
|
959
1170
|
decrypt(ciphertext, nonce) {
|
|
960
1171
|
return this.decrypt_raw(ciphertext.map((c) => {
|
|
961
1172
|
if (c.length !== 32) {
|
|
@@ -965,6 +1176,12 @@ class RescueCipher {
|
|
|
965
1176
|
}), nonce);
|
|
966
1177
|
}
|
|
967
1178
|
}
|
|
1179
|
+
/**
|
|
1180
|
+
* Generates the counter values for Rescue cipher CTR mode.
|
|
1181
|
+
* @param nonce - The initial nonce as a bigint.
|
|
1182
|
+
* @param nBlocks - The number of blocks to generate counters for.
|
|
1183
|
+
* @returns An array of counter values as bigints.
|
|
1184
|
+
*/
|
|
968
1185
|
function getCounter(nonce, nBlocks) {
|
|
969
1186
|
const counter = [];
|
|
970
1187
|
for (let i = 0n; i < nBlocks; ++i) {
|
|
@@ -977,10 +1194,203 @@ function getCounter(nonce, nBlocks) {
|
|
|
977
1194
|
return counter;
|
|
978
1195
|
}
|
|
979
1196
|
|
|
1197
|
+
// The arcisEd25519 signature scheme. This is essentially ed25519 but we use the hash function
|
|
1198
|
+
// SHA3-512 instead of SHA-512 since its multiplicative depth is much lower, which
|
|
1199
|
+
// makes it much better suited to be evaluated in MPC.
|
|
1200
|
+
// Those are the parameters specified [here](https://datatracker.ietf.org/doc/html/rfc8032#section-5.1)
|
|
1201
|
+
// (except for the hash function, see above). The below is copied from [here](https://github.com/paulmillr/noble-curves/blob/main/src/ed25519.ts#L111).
|
|
1202
|
+
const arcisEd25519Defaults = (() => ({
|
|
1203
|
+
a: BigInt(-1),
|
|
1204
|
+
d: BigInt('37095705934669439343138083508754565189542113879843219016388785533085940283555'),
|
|
1205
|
+
Fp: ed25519.CURVE.Fp,
|
|
1206
|
+
n: BigInt('7237005577332262213973186563042994240857116359379907606001950938285454250989'),
|
|
1207
|
+
h: BigInt(8),
|
|
1208
|
+
Gx: BigInt('15112221349535400772501151409588531511454012693041857206046113283949847762202'),
|
|
1209
|
+
Gy: BigInt('46316835694926478169428394003475163141307993866256225615783033603165251855960'),
|
|
1210
|
+
hash: sha3_512,
|
|
1211
|
+
randomBytes: randomBytes$1,
|
|
1212
|
+
adjustScalarBytes,
|
|
1213
|
+
uvRatio,
|
|
1214
|
+
}))();
|
|
1215
|
+
/**
|
|
1216
|
+
* Clamps a 32-byte scalar as required by the Ed25519 signature scheme.
|
|
1217
|
+
* See: https://datatracker.ietf.org/doc/html/rfc8032#section-5.1.5
|
|
1218
|
+
* @param bytes - The 32-byte scalar to clamp.
|
|
1219
|
+
* @returns The clamped scalar as a Uint8Array.
|
|
1220
|
+
*/
|
|
1221
|
+
function adjustScalarBytes(bytes) {
|
|
1222
|
+
const clamped = bytes;
|
|
1223
|
+
clamped[0] &= 248;
|
|
1224
|
+
clamped[31] &= 127;
|
|
1225
|
+
clamped[31] |= 64;
|
|
1226
|
+
return clamped;
|
|
1227
|
+
}
|
|
1228
|
+
/**
|
|
1229
|
+
* Dummy function for compatibility; not used in the ArcisEd25519 signature scheme.
|
|
1230
|
+
* Always returns { isValid: true, value: 0n }.
|
|
1231
|
+
* @returns An object with isValid: true and value: 0n.
|
|
1232
|
+
*/
|
|
1233
|
+
function uvRatio() {
|
|
1234
|
+
return { isValid: true, value: 0n };
|
|
1235
|
+
}
|
|
1236
|
+
/**
|
|
1237
|
+
* Ed25519 curve instance using SHA3-512 for hashing, suitable for MPC (ArcisEd25519 signature scheme).
|
|
1238
|
+
* This is essentially Ed25519 but with SHA3-512 instead of SHA-512 for lower multiplicative depth.
|
|
1239
|
+
* See: https://datatracker.ietf.org/doc/html/rfc8032#section-5.1
|
|
1240
|
+
*/
|
|
1241
|
+
const arcisEd25519 = (() => twistedEdwards(arcisEd25519Defaults))();
|
|
1242
|
+
|
|
1243
|
+
/**
|
|
1244
|
+
* AES-128 cipher in Counter (CTR) mode, using HKDF-SHA3-256 to derive the key from a shared secret.
|
|
1245
|
+
* See: https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf (Section 6.5) for details on CTR mode.
|
|
1246
|
+
*/
|
|
1247
|
+
class Aes128Cipher {
|
|
1248
|
+
key;
|
|
1249
|
+
/**
|
|
1250
|
+
* Constructs an AES-128 cipher instance using a shared secret.
|
|
1251
|
+
* The key is derived using HKDF-SHA3-256.
|
|
1252
|
+
* @param sharedSecret - The shared secret to derive the AES key from.
|
|
1253
|
+
*/
|
|
1254
|
+
constructor(sharedSecret) {
|
|
1255
|
+
const aesKey = hkdfSync('sha3-256', sharedSecret, new Uint8Array(), new Uint8Array(), 16);
|
|
1256
|
+
this.key = new Uint8Array(aesKey);
|
|
1257
|
+
}
|
|
1258
|
+
/**
|
|
1259
|
+
* Encrypts the plaintext array in Counter (CTR) mode.
|
|
1260
|
+
* @param plaintext - The data to encrypt.
|
|
1261
|
+
* @param nonce - An 8-byte nonce for CTR mode.
|
|
1262
|
+
* @returns The encrypted ciphertext as a Uint8Array.
|
|
1263
|
+
* @throws Error if the nonce is not 8 bytes long.
|
|
1264
|
+
*/
|
|
1265
|
+
encrypt(plaintext, nonce) {
|
|
1266
|
+
if (nonce.length !== 8) {
|
|
1267
|
+
throw Error(`nonce must be of length 8 (found ${nonce.length})`);
|
|
1268
|
+
}
|
|
1269
|
+
const paddedNonce = Buffer.concat([nonce, Buffer.alloc(16 - nonce.length, 0)]);
|
|
1270
|
+
const cipher = createCipheriv('aes-128-ctr', this.key, paddedNonce);
|
|
1271
|
+
const ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]);
|
|
1272
|
+
return new Uint8Array(ciphertext);
|
|
1273
|
+
}
|
|
1274
|
+
/**
|
|
1275
|
+
* Decrypts the ciphertext array in Counter (CTR) mode.
|
|
1276
|
+
* @param ciphertext - The data to decrypt.
|
|
1277
|
+
* @param nonce - An 8-byte nonce for CTR mode.
|
|
1278
|
+
* @returns The decrypted plaintext as a Uint8Array.
|
|
1279
|
+
* @throws Error if the nonce is not 8 bytes long.
|
|
1280
|
+
*/
|
|
1281
|
+
decrypt(ciphertext, nonce) {
|
|
1282
|
+
if (nonce.length !== 8) {
|
|
1283
|
+
throw Error(`nonce must be of length 8 (found ${nonce.length})`);
|
|
1284
|
+
}
|
|
1285
|
+
const paddedNonce = Buffer.concat([nonce, Buffer.alloc(16 - nonce.length, 0)]);
|
|
1286
|
+
const cipher = createDecipheriv('aes-128-ctr', this.key, paddedNonce);
|
|
1287
|
+
const decrypted = Buffer.concat([cipher.update(ciphertext), cipher.final()]);
|
|
1288
|
+
return new Uint8Array(decrypted);
|
|
1289
|
+
}
|
|
1290
|
+
}
|
|
1291
|
+
|
|
1292
|
+
/**
|
|
1293
|
+
* AES-192 cipher in Counter (CTR) mode, using HKDF-SHA3-256 to derive the key from a shared secret.
|
|
1294
|
+
* See: https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf (Section 6.5) for details on CTR mode.
|
|
1295
|
+
*/
|
|
1296
|
+
class Aes192Cipher {
|
|
1297
|
+
key;
|
|
1298
|
+
/**
|
|
1299
|
+
* Constructs an AES-192 cipher instance using a shared secret.
|
|
1300
|
+
* The key is derived using HKDF-SHA3-256.
|
|
1301
|
+
* @param sharedSecret - The shared secret to derive the AES key from.
|
|
1302
|
+
*/
|
|
1303
|
+
constructor(sharedSecret) {
|
|
1304
|
+
const aesKey = hkdfSync('sha3-256', sharedSecret, new Uint8Array(), new Uint8Array(), 24);
|
|
1305
|
+
this.key = new Uint8Array(aesKey);
|
|
1306
|
+
}
|
|
1307
|
+
/**
|
|
1308
|
+
* Encrypts the plaintext array in Counter (CTR) mode.
|
|
1309
|
+
* @param plaintext - The data to encrypt.
|
|
1310
|
+
* @param nonce - An 8-byte nonce for CTR mode.
|
|
1311
|
+
* @returns The encrypted ciphertext as a Uint8Array.
|
|
1312
|
+
* @throws Error if the nonce is not 8 bytes long.
|
|
1313
|
+
*/
|
|
1314
|
+
encrypt(plaintext, nonce) {
|
|
1315
|
+
if (nonce.length !== 8) {
|
|
1316
|
+
throw Error(`nonce must be of length 8 (found ${nonce.length})`);
|
|
1317
|
+
}
|
|
1318
|
+
const paddedNonce = Buffer.concat([nonce, Buffer.alloc(16 - nonce.length, 0)]);
|
|
1319
|
+
const cipher = createCipheriv('aes-192-ctr', this.key, paddedNonce);
|
|
1320
|
+
const ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]);
|
|
1321
|
+
return new Uint8Array(ciphertext);
|
|
1322
|
+
}
|
|
1323
|
+
/**
|
|
1324
|
+
* Decrypts the ciphertext array in Counter (CTR) mode.
|
|
1325
|
+
* @param ciphertext - The data to decrypt.
|
|
1326
|
+
* @param nonce - An 8-byte nonce for CTR mode.
|
|
1327
|
+
* @returns The decrypted plaintext as a Uint8Array.
|
|
1328
|
+
* @throws Error if the nonce is not 8 bytes long.
|
|
1329
|
+
*/
|
|
1330
|
+
decrypt(ciphertext, nonce) {
|
|
1331
|
+
if (nonce.length !== 8) {
|
|
1332
|
+
throw Error(`nonce must be of length 8 (found ${nonce.length})`);
|
|
1333
|
+
}
|
|
1334
|
+
const paddedNonce = Buffer.concat([nonce, Buffer.alloc(16 - nonce.length, 0)]);
|
|
1335
|
+
const cipher = createDecipheriv('aes-192-ctr', this.key, paddedNonce);
|
|
1336
|
+
const decrypted = Buffer.concat([cipher.update(ciphertext), cipher.final()]);
|
|
1337
|
+
return new Uint8Array(decrypted);
|
|
1338
|
+
}
|
|
1339
|
+
}
|
|
1340
|
+
|
|
1341
|
+
/**
|
|
1342
|
+
* AES-256 cipher in Counter (CTR) mode, using HKDF-SHA3-256 to derive the key from a shared secret.
|
|
1343
|
+
* See: https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf (Section 6.5) for details on CTR mode.
|
|
1344
|
+
*/
|
|
1345
|
+
class Aes256Cipher {
|
|
1346
|
+
key;
|
|
1347
|
+
/**
|
|
1348
|
+
* Constructs an AES-256 cipher instance using a shared secret.
|
|
1349
|
+
* The key is derived using HKDF-SHA3-256.
|
|
1350
|
+
* @param sharedSecret - The shared secret to derive the AES key from.
|
|
1351
|
+
*/
|
|
1352
|
+
constructor(sharedSecret) {
|
|
1353
|
+
const aesKey = hkdfSync('sha3-256', sharedSecret, new Uint8Array(), new Uint8Array(), 32);
|
|
1354
|
+
this.key = new Uint8Array(aesKey);
|
|
1355
|
+
}
|
|
1356
|
+
/**
|
|
1357
|
+
* Encrypts the plaintext array in Counter (CTR) mode.
|
|
1358
|
+
* @param plaintext - The data to encrypt.
|
|
1359
|
+
* @param nonce - An 8-byte nonce for CTR mode.
|
|
1360
|
+
* @returns The encrypted ciphertext as a Uint8Array.
|
|
1361
|
+
* @throws Error if the nonce is not 8 bytes long.
|
|
1362
|
+
*/
|
|
1363
|
+
encrypt(plaintext, nonce) {
|
|
1364
|
+
if (nonce.length !== 8) {
|
|
1365
|
+
throw Error(`nonce must be of length 8 (found ${nonce.length})`);
|
|
1366
|
+
}
|
|
1367
|
+
const paddedNonce = Buffer.concat([nonce, Buffer.alloc(16 - nonce.length, 0)]);
|
|
1368
|
+
const cipher = createCipheriv('aes-256-ctr', this.key, paddedNonce);
|
|
1369
|
+
const ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]);
|
|
1370
|
+
return new Uint8Array(ciphertext);
|
|
1371
|
+
}
|
|
1372
|
+
/**
|
|
1373
|
+
* Decrypts the ciphertext array in Counter (CTR) mode.
|
|
1374
|
+
* @param ciphertext - The data to decrypt.
|
|
1375
|
+
* @param nonce - An 8-byte nonce for CTR mode.
|
|
1376
|
+
* @returns The decrypted plaintext as a Uint8Array.
|
|
1377
|
+
* @throws Error if the nonce is not 8 bytes long.
|
|
1378
|
+
*/
|
|
1379
|
+
decrypt(ciphertext, nonce) {
|
|
1380
|
+
if (nonce.length !== 8) {
|
|
1381
|
+
throw Error(`nonce must be of length 8 (found ${nonce.length})`);
|
|
1382
|
+
}
|
|
1383
|
+
const paddedNonce = Buffer.concat([nonce, Buffer.alloc(16 - nonce.length, 0)]);
|
|
1384
|
+
const cipher = createDecipheriv('aes-256-ctr', this.key, paddedNonce);
|
|
1385
|
+
const decrypted = Buffer.concat([cipher.update(ciphertext), cipher.final()]);
|
|
1386
|
+
return new Uint8Array(decrypted);
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
|
|
980
1390
|
var address = "BKck65TgoKRokMjQM3datB9oRwJ8rAj2jxPXvHXUvcL6";
|
|
981
1391
|
var metadata = {
|
|
982
1392
|
name: "arcium",
|
|
983
|
-
version: "0.1.
|
|
1393
|
+
version: "0.1.47",
|
|
984
1394
|
spec: "0.1.0",
|
|
985
1395
|
description: "The Arcium program"
|
|
986
1396
|
};
|
|
@@ -11522,32 +11932,75 @@ var ARCIUM_IDL = /*#__PURE__*/Object.freeze({
|
|
|
11522
11932
|
types: types
|
|
11523
11933
|
});
|
|
11524
11934
|
|
|
11935
|
+
/**
|
|
11936
|
+
* The deployed address of the Arcium program, as specified in the IDL.
|
|
11937
|
+
*/
|
|
11525
11938
|
const ARCIUM_ADDR = address;
|
|
11526
11939
|
|
|
11527
|
-
|
|
11940
|
+
/**
|
|
11941
|
+
* Seed for ClockAccount PDA
|
|
11942
|
+
* @constant {string}
|
|
11943
|
+
*/
|
|
11528
11944
|
const CLOCK_ACC_SEED = 'ClockAccount';
|
|
11529
|
-
|
|
11945
|
+
/**
|
|
11946
|
+
* Seed for StakingPoolAccount PDA
|
|
11947
|
+
* @constant {string}
|
|
11948
|
+
*/
|
|
11530
11949
|
const POOL_ACC_SEED = 'StakingPoolAccount';
|
|
11531
|
-
|
|
11950
|
+
/**
|
|
11951
|
+
* Seed for ComputationAccount PDA
|
|
11952
|
+
* @constant {string}
|
|
11953
|
+
*/
|
|
11532
11954
|
const COMPUTATION_ACC_SEED = 'ComputationAccount';
|
|
11533
|
-
|
|
11955
|
+
/**
|
|
11956
|
+
* Seed for Mempool PDA
|
|
11957
|
+
* @constant {string}
|
|
11958
|
+
*/
|
|
11534
11959
|
const MEMPOOL_ACC_SEED = 'Mempool';
|
|
11535
|
-
|
|
11960
|
+
/**
|
|
11961
|
+
* Seed for ExecutingPoolAccount PDA
|
|
11962
|
+
* @constant {string}
|
|
11963
|
+
*/
|
|
11536
11964
|
const EXEC_POOL_ACC_SEED = 'Execpool';
|
|
11537
|
-
|
|
11965
|
+
/**
|
|
11966
|
+
* Seed for ClusterAccount PDA
|
|
11967
|
+
* @constant {string}
|
|
11968
|
+
*/
|
|
11538
11969
|
const CLUSTER_ACC_SEED = 'Cluster';
|
|
11539
|
-
|
|
11970
|
+
/**
|
|
11971
|
+
* Seed for ArxNodeAccount PDA
|
|
11972
|
+
* @constant {string}
|
|
11973
|
+
*/
|
|
11540
11974
|
const ARX_NODE_ACC_SEED = 'ArxNode';
|
|
11541
|
-
|
|
11975
|
+
/**
|
|
11976
|
+
* Seed for MXEAccAccount PDA
|
|
11977
|
+
* @constant {string}
|
|
11978
|
+
*/
|
|
11542
11979
|
const MXE_ACC_ACC_SEED = 'PersistentMXEAccount';
|
|
11543
|
-
|
|
11980
|
+
/**
|
|
11981
|
+
* Seed for CompDefAccount PDA
|
|
11982
|
+
* @constant {string}
|
|
11983
|
+
*/
|
|
11544
11984
|
const COMP_DEF_ACC_SEED = 'ComputationDefinitionAccount';
|
|
11985
|
+
/**
|
|
11986
|
+
* Maximum number of bytes that can be reallocated per instruction.
|
|
11987
|
+
* @constant {number}
|
|
11988
|
+
*/
|
|
11545
11989
|
const MAX_REALLOC_PER_IX = 10240;
|
|
11546
|
-
|
|
11990
|
+
/**
|
|
11991
|
+
* Maximum number of bytes that can be uploaded in a single transaction with the upload instruction.
|
|
11992
|
+
* @constant {number}
|
|
11993
|
+
*/
|
|
11547
11994
|
const MAX_UPLOAD_PER_TX_BYTES = 814;
|
|
11548
|
-
|
|
11549
|
-
|
|
11550
|
-
|
|
11995
|
+
/**
|
|
11996
|
+
* Maximum size of an account in bytes (10MB = 10 * 1024 * 1024).
|
|
11997
|
+
* @constant {number}
|
|
11998
|
+
*/
|
|
11999
|
+
const MAX_ACCOUNT_SIZE = 10485760;
|
|
12000
|
+
/**
|
|
12001
|
+
* Maximum number of arcium embiggen instructions allowed in a single transaction (due to compute unit limits).
|
|
12002
|
+
* @constant {number}
|
|
12003
|
+
*/
|
|
11551
12004
|
const MAX_EMBIGGEN_IX_PER_TX = 18;
|
|
11552
12005
|
|
|
11553
12006
|
const TINY_MEMPOOL_ACC_NAME = 'tinyMempool';
|
|
@@ -11650,9 +12103,19 @@ const EXECPOOL_DISCRIMINATOR_MAP = {
|
|
|
11650
12103
|
[MEDIUM_EXECPOOL_DISCRIMINATOR.toString()]: MEDIUM_EXECPOOL_ACC_NAME,
|
|
11651
12104
|
[LARGE_EXECPOOL_DISCRIMINATOR.toString()]: LARGE_EXECPOOL_ACC_NAME,
|
|
11652
12105
|
};
|
|
12106
|
+
/**
|
|
12107
|
+
* Returns the public key of the deployed Arcium program on Solana.
|
|
12108
|
+
* @returns The Arcium program's public key.
|
|
12109
|
+
*/
|
|
11653
12110
|
function getArciumProgAddress() {
|
|
11654
12111
|
return new anchor.web3.PublicKey(ARCIUM_ADDR);
|
|
11655
12112
|
}
|
|
12113
|
+
/**
|
|
12114
|
+
* Fetches the DA (Data Availability) info for all nodes in a cluster.
|
|
12115
|
+
* @param provider - The Anchor provider to use for fetching accounts.
|
|
12116
|
+
* @param clusterAddr - The public key of the cluster account.
|
|
12117
|
+
* @returns An array of NodeDAInfo objects for each node in the cluster.
|
|
12118
|
+
*/
|
|
11656
12119
|
async function getClusterDAInfo(provider, clusterAddr) {
|
|
11657
12120
|
const program = getArciumProgram(provider);
|
|
11658
12121
|
const clusterAcc = await program.account.cluster.fetch(clusterAddr);
|
|
@@ -11663,6 +12126,13 @@ async function getClusterDAInfo(provider, clusterAddr) {
|
|
|
11663
12126
|
return { solanaPubkey: nodeAccPubkey, x25519Pubkey: Uint8Array.from(nodeAcc.encryptionPubkey) };
|
|
11664
12127
|
}));
|
|
11665
12128
|
}
|
|
12129
|
+
/**
|
|
12130
|
+
* Fetches and decodes the mempool account data for any mempool account size.
|
|
12131
|
+
* @param provider - The Anchor provider to use for fetching accounts.
|
|
12132
|
+
* @param mempoolAccPubkey - The public key of the mempool account.
|
|
12133
|
+
* @returns The decoded mempool account data.
|
|
12134
|
+
* @throws Error if the account cannot be fetched or the discriminator is unknown.
|
|
12135
|
+
*/
|
|
11666
12136
|
async function getMempoolAccData(provider, mempoolAccPubkey) {
|
|
11667
12137
|
const accData = await provider.connection.getAccountInfo(mempoolAccPubkey);
|
|
11668
12138
|
if (accData === null) {
|
|
@@ -11676,6 +12146,13 @@ async function getMempoolAccData(provider, mempoolAccPubkey) {
|
|
|
11676
12146
|
const program = getArciumProgram(provider);
|
|
11677
12147
|
return program.coder.accounts.decode(accName, accData.data);
|
|
11678
12148
|
}
|
|
12149
|
+
/**
|
|
12150
|
+
* Fetches and decodes the executing pool account data for any pool size.
|
|
12151
|
+
* @param provider - The Anchor provider to use for fetching accounts.
|
|
12152
|
+
* @param executingPoolAccPubkey - The public key of the executing pool account.
|
|
12153
|
+
* @returns The decoded executing pool account data.
|
|
12154
|
+
* @throws Error if the account cannot be fetched or the discriminator is unknown.
|
|
12155
|
+
*/
|
|
11679
12156
|
async function getExecutingPoolAccData(provider, executingPoolAccPubkey) {
|
|
11680
12157
|
const accData = await provider.connection.getAccountInfo(executingPoolAccPubkey);
|
|
11681
12158
|
if (accData === null) {
|
|
@@ -11689,6 +12166,16 @@ async function getExecutingPoolAccData(provider, executingPoolAccPubkey) {
|
|
|
11689
12166
|
const program = getArciumProgram(provider);
|
|
11690
12167
|
return program.coder.accounts.decode(accName, accData.data);
|
|
11691
12168
|
}
|
|
12169
|
+
/**
|
|
12170
|
+
* Uploads a circuit to the blockchain, splitting it into multiple accounts if necessary.
|
|
12171
|
+
* @param provider - The Anchor provider to use for transactions.
|
|
12172
|
+
* @param circuitName - The name of the circuit.
|
|
12173
|
+
* @param mxeProgramID - The public key of the MXE program.
|
|
12174
|
+
* @param rawCircuit - The raw circuit data as a Uint8Array.
|
|
12175
|
+
* @param logging - Whether to log progress (default: true).
|
|
12176
|
+
* @param chunkSize - The number of upload transactions to send in parallel (default: 500).
|
|
12177
|
+
* @returns An array of transaction signatures for all upload and finalize transactions.
|
|
12178
|
+
*/
|
|
11692
12179
|
async function uploadCircuit(provider, circuitName, mxeProgramID, rawCircuit, logging = true, chunkSize = 500) {
|
|
11693
12180
|
const numAccs = Math.ceil(rawCircuit.length / (MAX_ACCOUNT_SIZE - 9));
|
|
11694
12181
|
const compDefAccInfo = getCompDefAccInfo(circuitName, mxeProgramID);
|
|
@@ -11703,6 +12190,13 @@ async function uploadCircuit(provider, circuitName, mxeProgramID, rawCircuit, lo
|
|
|
11703
12190
|
sigs.push(await signAndSendWithBlockhash(provider, finalizeCompDefTx, await provider.connection.getLatestBlockhash()));
|
|
11704
12191
|
return sigs;
|
|
11705
12192
|
}
|
|
12193
|
+
/**
|
|
12194
|
+
* Builds a transaction to finalize a computation definition.
|
|
12195
|
+
* @param provider - The Anchor provider to use for transactions.
|
|
12196
|
+
* @param compDefOffset - The offset of the computation definition.
|
|
12197
|
+
* @param mxeProgramID - The public key of the MXE program.
|
|
12198
|
+
* @returns The transaction to finalize the computation definition.
|
|
12199
|
+
*/
|
|
11706
12200
|
async function buildFinalizeCompDefTx(provider, compDefOffset, mxeProgramID) {
|
|
11707
12201
|
const program = getArciumProgram(provider);
|
|
11708
12202
|
const compDefOffsetBuffer = Buffer.alloc(4);
|
|
@@ -11804,35 +12298,78 @@ async function signAndSendWithBlockhash(provider, tx, block) {
|
|
|
11804
12298
|
tx.lastValidBlockHeight = block.lastValidBlockHeight;
|
|
11805
12299
|
return provider.sendAndConfirm(tx, [], { commitment: 'confirmed' });
|
|
11806
12300
|
}
|
|
12301
|
+
/**
|
|
12302
|
+
* Returns the base seed for an Arcium account, given its name.
|
|
12303
|
+
* @param accName - The name of the account.
|
|
12304
|
+
* @returns The base seed as a Uint8Array.
|
|
12305
|
+
*/
|
|
11807
12306
|
function getArciumAccountBaseSeed(accName) {
|
|
11808
12307
|
return Buffer.from(accName, 'utf-8');
|
|
11809
12308
|
}
|
|
12309
|
+
/**
|
|
12310
|
+
* Computes the offset for a computation definition account, based on the circuit name.
|
|
12311
|
+
* @param circuitName - The name of the circuit.
|
|
12312
|
+
* @returns The offset as a 4-byte Uint8Array.
|
|
12313
|
+
*/
|
|
11810
12314
|
function getCompDefAccOffset(circuitName) {
|
|
11811
12315
|
const hash = new Uint8Array(sha256([Buffer.from(circuitName, 'utf-8')]));
|
|
11812
12316
|
return hash.slice(0, 4);
|
|
11813
12317
|
}
|
|
12318
|
+
/**
|
|
12319
|
+
* Returns an Anchor program instance for the Arcium program.
|
|
12320
|
+
* @param provider - The Anchor provider to use.
|
|
12321
|
+
* @returns The Anchor program instance for Arcium.
|
|
12322
|
+
*/
|
|
11814
12323
|
function getArciumProgram(provider) {
|
|
11815
12324
|
return new Program(ARCIUM_IDL, provider);
|
|
11816
12325
|
}
|
|
12326
|
+
/**
|
|
12327
|
+
* Returns a read-only Anchor program instance for the Arcium program.
|
|
12328
|
+
* @param provider - The Anchor provider to use.
|
|
12329
|
+
* @returns The Anchor program instance for Arcium.
|
|
12330
|
+
*/
|
|
11817
12331
|
function getArciumProgramReadonly(provider) {
|
|
11818
12332
|
return new Program(ARCIUM_IDL, provider);
|
|
11819
12333
|
}
|
|
12334
|
+
/**
|
|
12335
|
+
* Returns the PDA (program-derived address) for an ArxNode account given the program ID and node offset.
|
|
12336
|
+
* @param arciumProgramID - The public key of the Arcium program.
|
|
12337
|
+
* @param nodeOffset - The offset of the node.
|
|
12338
|
+
* @returns The PDA for the ArxNode account.
|
|
12339
|
+
*/
|
|
11820
12340
|
function getArxAccPDA(arciumProgramID, nodeOffset) {
|
|
11821
12341
|
const nodeOffsetBuffer = Buffer.alloc(4);
|
|
11822
12342
|
nodeOffsetBuffer.writeUInt32LE(nodeOffset, 0);
|
|
11823
12343
|
return anchor.web3.PublicKey.findProgramAddressSync([Buffer.from('ArxNode', 'utf-8'), nodeOffsetBuffer], arciumProgramID)[0];
|
|
11824
12344
|
}
|
|
12345
|
+
/**
|
|
12346
|
+
* Returns the public key and offset for a computation definition account, given the circuit name and MXE program ID.
|
|
12347
|
+
* @param circuitName - The name of the circuit.
|
|
12348
|
+
* @param mxeProgramID - The public key of the MXE program.
|
|
12349
|
+
* @returns An object containing the public key and offset for the computation definition account.
|
|
12350
|
+
*/
|
|
11825
12351
|
function getCompDefAccInfo(circuitName, mxeProgramID) {
|
|
11826
12352
|
const offset = getCompDefAccOffset(circuitName);
|
|
11827
12353
|
const pda = getCompDefAccPDA(getArciumProgAddress(), mxeProgramID, offset);
|
|
11828
12354
|
return { pubkey: pda, offset: Buffer.from(offset).readUInt32LE(0) };
|
|
11829
12355
|
}
|
|
12356
|
+
/**
|
|
12357
|
+
* Returns the PDA for a computation definition account, given the program ID, MXE program ID, and offset.
|
|
12358
|
+
* @param arciumProgramID - The public key of the Arcium program.
|
|
12359
|
+
* @param mxeProgramID - The public key of the MXE program.
|
|
12360
|
+
* @param offset - The offset as a Uint8Array.
|
|
12361
|
+
* @returns The PDA for the computation definition account.
|
|
12362
|
+
*/
|
|
11830
12363
|
function getCompDefAccPDA(arciumProgramID, mxeProgramID, offset) {
|
|
11831
12364
|
return anchor.web3.PublicKey.findProgramAddressSync([Buffer.from('ComputationDefinitionAccount', 'utf-8'), mxeProgramID.toBuffer(), offset], arciumProgramID)[0];
|
|
11832
12365
|
}
|
|
11833
12366
|
|
|
11834
|
-
|
|
11835
|
-
|
|
12367
|
+
/**
|
|
12368
|
+
* Reads local Arcium environment information from environment variables.
|
|
12369
|
+
* Only available in Node.js and when testing locally.
|
|
12370
|
+
* @returns The local Arcium environment configuration.
|
|
12371
|
+
* @throws Error if called in a browser or if required environment variables are missing or invalid.
|
|
12372
|
+
*/
|
|
11836
12373
|
function getArciumEnv() {
|
|
11837
12374
|
if (isBrowser()) {
|
|
11838
12375
|
throw new Error('Arcium local env is not available in browser.');
|
|
@@ -12090,12 +12627,29 @@ class LogScanner {
|
|
|
12090
12627
|
}
|
|
12091
12628
|
}
|
|
12092
12629
|
|
|
12630
|
+
/**
|
|
12631
|
+
* Waits for the finalization of a computation by listening for the finalizeComputationEvent.
|
|
12632
|
+
* Resolves with the transaction signature once the computation is finalized.
|
|
12633
|
+
* @param provider - The Anchor provider to use for event listening.
|
|
12634
|
+
* @param computationOffset - The offset of the computation to wait for.
|
|
12635
|
+
* @param mxeProgramId - The public key of the MXE program.
|
|
12636
|
+
* @param commitment - (Optional) The desired finality/commitment level (default: 'confirmed').
|
|
12637
|
+
* @returns The transaction signature of the finalization event.
|
|
12638
|
+
*/
|
|
12093
12639
|
async function awaitComputationFinalization(provider, computationOffset, mxeProgramId, commitment = 'confirmed') {
|
|
12094
12640
|
const arciumProgram = getArciumProgram(provider);
|
|
12095
12641
|
const eventListener = new EventManager(arciumProgram.programId, provider, arciumProgram.coder);
|
|
12096
12642
|
const finalizeComp = await awaitEvent(eventListener, 'finalizeComputationEvent', (e) => mxeProgramId.equals(e.mxeProgramId) && e.computationOffset.eq(computationOffset), commitment);
|
|
12097
12643
|
return finalizeComp.sig;
|
|
12098
12644
|
}
|
|
12645
|
+
/**
|
|
12646
|
+
* Waits for a specific event to occur, matching a custom check, and returns the event and its signature.
|
|
12647
|
+
* @param eventListener - The EventManager instance to use for listening.
|
|
12648
|
+
* @param eventName - The name of the event to listen for.
|
|
12649
|
+
* @param eventCheck - A predicate function to check if the event matches the desired criteria.
|
|
12650
|
+
* @param commitment - (Optional) The desired finality/commitment level (default: 'confirmed').
|
|
12651
|
+
* @returns An object containing the event and its transaction signature.
|
|
12652
|
+
*/
|
|
12099
12653
|
async function awaitEvent(eventListener, eventName, eventCheck, commitment = 'confirmed') {
|
|
12100
12654
|
const foundEvent = await new Promise((res) => {
|
|
12101
12655
|
const listenerId = eventListener.addEventListener(eventName, (event, _slot, signature) => {
|
|
@@ -12107,54 +12661,108 @@ async function awaitEvent(eventListener, eventName, eventCheck, commitment = 'co
|
|
|
12107
12661
|
return { event: foundEvent[0], sig: foundEvent[1] };
|
|
12108
12662
|
}
|
|
12109
12663
|
|
|
12664
|
+
/**
|
|
12665
|
+
* Returns the public key of the deployed Arcium program on Solana.
|
|
12666
|
+
* @returns The Arcium program's public key.
|
|
12667
|
+
*/
|
|
12110
12668
|
function getArciumProgramId() {
|
|
12111
12669
|
return new PublicKey('BKck65TgoKRokMjQM3datB9oRwJ8rAj2jxPXvHXUvcL6');
|
|
12112
12670
|
}
|
|
12113
|
-
|
|
12671
|
+
/**
|
|
12672
|
+
* Derives the computation account address for a given MXE program ID and offset.
|
|
12673
|
+
* @param mxeProgramId - The public key of the MXE program.
|
|
12674
|
+
* @param offset - The computation offset as an anchor.BN.
|
|
12675
|
+
* @returns The derived computation account public key.
|
|
12676
|
+
*/
|
|
12677
|
+
function getComputationAccAddress(mxeProgramId, offset) {
|
|
12114
12678
|
const seeds = [Buffer.from(COMPUTATION_ACC_SEED), mxeProgramId.toBuffer(), offset.toArrayLike(Buffer, 'le', 8)];
|
|
12115
12679
|
return generateArciumPDAFrom(seeds)[0];
|
|
12116
12680
|
}
|
|
12117
|
-
|
|
12681
|
+
/**
|
|
12682
|
+
* Derives the mempool account address for a given MXE program ID.
|
|
12683
|
+
* @param mxeProgramId - The public key of the MXE program.
|
|
12684
|
+
* @returns The derived mempool account public key.
|
|
12685
|
+
*/
|
|
12686
|
+
function getMempoolAccAddress(mxeProgramId) {
|
|
12118
12687
|
const seeds = [Buffer.from(MEMPOOL_ACC_SEED), mxeProgramId.toBuffer()];
|
|
12119
12688
|
return generateArciumPDAFrom(seeds)[0];
|
|
12120
12689
|
}
|
|
12121
|
-
|
|
12690
|
+
/**
|
|
12691
|
+
* Derives the executing pool account address for a given MXE program ID.
|
|
12692
|
+
* @param mxeProgramId - The public key of the MXE program.
|
|
12693
|
+
* @returns The derived executing pool account public key.
|
|
12694
|
+
*/
|
|
12695
|
+
function getExecutingPoolAccAddress(mxeProgramId) {
|
|
12122
12696
|
const seeds = [Buffer.from(EXEC_POOL_ACC_SEED), mxeProgramId.toBuffer()];
|
|
12123
12697
|
return generateArciumPDAFrom(seeds)[0];
|
|
12124
12698
|
}
|
|
12125
|
-
|
|
12699
|
+
/**
|
|
12700
|
+
* Derives the staking pool account address.
|
|
12701
|
+
* @returns The derived staking pool account public key.
|
|
12702
|
+
*/
|
|
12703
|
+
function getStakingPoolAccAddress() {
|
|
12126
12704
|
const seeds = [Buffer.from(POOL_ACC_SEED)];
|
|
12127
12705
|
return generateArciumPDAFrom(seeds)[0];
|
|
12128
12706
|
}
|
|
12129
|
-
|
|
12707
|
+
/**
|
|
12708
|
+
* Derives the clock account address.
|
|
12709
|
+
* @returns The derived clock account public key.
|
|
12710
|
+
*/
|
|
12711
|
+
function getClockAccAddress() {
|
|
12130
12712
|
const seeds = [Buffer.from(CLOCK_ACC_SEED)];
|
|
12131
12713
|
return generateArciumPDAFrom(seeds)[0];
|
|
12132
12714
|
}
|
|
12133
|
-
|
|
12715
|
+
/**
|
|
12716
|
+
* Derives the cluster account address for a given offset.
|
|
12717
|
+
* @param offset - The cluster offset as a number.
|
|
12718
|
+
* @returns The derived cluster account public key.
|
|
12719
|
+
*/
|
|
12720
|
+
function getClusterAccAddress(offset) {
|
|
12134
12721
|
const offsetBuffer = Buffer.alloc(4);
|
|
12135
12722
|
offsetBuffer.writeUInt32LE(offset, 0);
|
|
12136
12723
|
const seeds = [Buffer.from(CLUSTER_ACC_SEED), offsetBuffer];
|
|
12137
12724
|
return generateArciumPDAFrom(seeds)[0];
|
|
12138
12725
|
}
|
|
12139
|
-
|
|
12726
|
+
/**
|
|
12727
|
+
* Derives the ArxNode account address for a given offset.
|
|
12728
|
+
* @param offset - The ArxNode offset as a number.
|
|
12729
|
+
* @returns The derived ArxNode account public key.
|
|
12730
|
+
*/
|
|
12731
|
+
function getArxNodeAccAddress(offset) {
|
|
12140
12732
|
const offsetBuffer = Buffer.alloc(4);
|
|
12141
12733
|
offsetBuffer.writeUInt32LE(offset, 0);
|
|
12142
12734
|
const seeds = [Buffer.from(ARX_NODE_ACC_SEED), offsetBuffer];
|
|
12143
12735
|
return generateArciumPDAFrom(seeds)[0];
|
|
12144
12736
|
}
|
|
12145
|
-
|
|
12737
|
+
/**
|
|
12738
|
+
* Derives the MXE account address for a given MXE program ID.
|
|
12739
|
+
* @param mxeProgramId - The public key of the MXE program.
|
|
12740
|
+
* @returns The derived MXE account public key.
|
|
12741
|
+
*/
|
|
12742
|
+
function getMXEAccAddress(mxeProgramId) {
|
|
12146
12743
|
const seeds = [Buffer.from(MXE_ACC_ACC_SEED), mxeProgramId.toBuffer()];
|
|
12147
12744
|
return generateArciumPDAFrom(seeds)[0];
|
|
12148
12745
|
}
|
|
12149
|
-
|
|
12746
|
+
/**
|
|
12747
|
+
* Derives the computation definition account address for a given MXE program ID and offset.
|
|
12748
|
+
* @param mxeProgramId - The public key of the MXE program.
|
|
12749
|
+
* @param offset - The computation definition offset as a number.
|
|
12750
|
+
* @returns The derived computation definition account public key.
|
|
12751
|
+
*/
|
|
12752
|
+
function getCompDefAccAddress(mxeProgramId, offset) {
|
|
12150
12753
|
const offsetBuffer = Buffer.alloc(4);
|
|
12151
12754
|
offsetBuffer.writeUInt32LE(offset, 0);
|
|
12152
12755
|
const seeds = [Buffer.from(COMP_DEF_ACC_SEED), mxeProgramId.toBuffer(), offsetBuffer];
|
|
12153
12756
|
return generateArciumPDAFrom(seeds)[0];
|
|
12154
12757
|
}
|
|
12758
|
+
/**
|
|
12759
|
+
* Generates a program-derived address (PDA) from the provided seeds and the Arcium program ID.
|
|
12760
|
+
* @param seeds - An array of Buffer seeds used for PDA derivation.
|
|
12761
|
+
* @returns A tuple containing the derived public key and the bump seed.
|
|
12762
|
+
*/
|
|
12155
12763
|
function generateArciumPDAFrom(seeds) {
|
|
12156
12764
|
const programId = getArciumProgramId();
|
|
12157
12765
|
return PublicKey.findProgramAddressSync(seeds, programId);
|
|
12158
12766
|
}
|
|
12159
12767
|
|
|
12160
|
-
export { ARCIUM_ADDR, ARCIUM_IDL, CURVE25519_BASE_FIELD, CURVE25519_SCALAR_FIELD_MODULUS, DOUBLE_PRECISION_MANTISSA, Matrix, RescueCipher, RescueDesc, RescuePrimeHash, awaitComputationFinalization, buildFinalizeCompDefTx, deserializeLE, encodeAsRescueEncryptable, encryptForDA, genRawShares, generateRandomFieldElem, getArciumAccountBaseSeed, getArciumEnv, getArciumProgAddress, getArciumProgram, getArciumProgramId, getArciumProgramReadonly,
|
|
12768
|
+
export { ARCIUM_ADDR, ARCIUM_IDL, Aes128Cipher, Aes192Cipher, Aes256Cipher, CURVE25519_BASE_FIELD, CURVE25519_SCALAR_FIELD_MODULUS, DOUBLE_PRECISION_MANTISSA, Matrix, RescueCipher, RescueDesc, RescuePrimeHash, arcisEd25519, awaitComputationFinalization, buildFinalizeCompDefTx, deserializeLE, encodeAsRescueEncryptable, encryptForDA, genRawShares, generateRandomFieldElem, getArciumAccountBaseSeed, getArciumEnv, getArciumProgAddress, getArciumProgram, getArciumProgramId, getArciumProgramReadonly, getArxNodeAccAddress, getClockAccAddress, getClusterAccAddress, getClusterDAInfo, getCompDefAccAddress, getCompDefAccOffset, getComputationAccAddress, getEncryptionKey, getExecutingPoolAccAddress, getExecutingPoolAccData, getMXEAccAddress, getMempoolAccAddress, getMempoolAccData, getStakingPoolAccAddress, positiveModulo, randMatrix, secretShareInputs, secretShareValue, serializeLE, sha256, toVec, uploadCircuit };
|