@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/build/index.cjs CHANGED
@@ -6,6 +6,8 @@ var ed25519 = require('@noble/curves/ed25519');
6
6
  var anchor = require('@coral-xyz/anchor');
7
7
  var sha3 = require('@noble/hashes/sha3');
8
8
  var modular = require('@noble/curves/abstract/modular');
9
+ var utils = require('@noble/hashes/utils');
10
+ var edwards = require('@noble/curves/abstract/edwards');
9
11
  var web3_js = require('@solana/web3.js');
10
12
 
11
13
  function _interopNamespaceDefault(e) {
@@ -27,7 +29,12 @@ function _interopNamespaceDefault(e) {
27
29
 
28
30
  var anchor__namespace = /*#__PURE__*/_interopNamespaceDefault(anchor);
29
31
 
30
- // Converts a bigint to an array of bits (least significant to most significant, in 2's complement representation).
32
+ /**
33
+ * Converts a bigint to an array of bits (least significant to most significant, in 2's complement representation).
34
+ * @param x - The bigint to convert.
35
+ * @param binSize - The number of bits to use in the representation.
36
+ * @returns An array of booleans representing the bits of x.
37
+ */
31
38
  function toBinLE(x, binSize) {
32
39
  const res = [];
33
40
  for (let i = 0; i < binSize; ++i) {
@@ -35,7 +42,11 @@ function toBinLE(x, binSize) {
35
42
  }
36
43
  return res;
37
44
  }
38
- // Converts an array of bits (least significant to most significant, in 2's complement representation) to a bigint.
45
+ /**
46
+ * Converts an array of bits (least significant to most significant, in 2's complement representation) to a bigint.
47
+ * @param xBin - The array of bits to convert.
48
+ * @returns The bigint represented by the bit array.
49
+ */
39
50
  function fromBinLE(xBin) {
40
51
  let res = 0n;
41
52
  for (let i = 0; i < xBin.length - 1; ++i) {
@@ -43,8 +54,14 @@ function fromBinLE(xBin) {
43
54
  }
44
55
  return res - (BigInt(xBin[xBin.length - 1]) << BigInt(xBin.length - 1));
45
56
  }
46
- // Binary adder between x and y (we assume that xBin and yBin are of same length,
47
- // and that the length is large enough to represent the sum of the two).
57
+ /**
58
+ * Binary adder between x and y (assumes xBin and yBin are of the same length and large enough to represent the sum).
59
+ * @param xBin - The first operand as a bit array.
60
+ * @param yBin - The second operand as a bit array.
61
+ * @param carryIn - The initial carry-in value.
62
+ * @param binSize - The number of bits to use in the operation.
63
+ * @returns The sum as a bit array.
64
+ */
48
65
  function adder(xBin, yBin, carryIn, binSize) {
49
66
  const res = [];
50
67
  let carry = carryIn;
@@ -59,12 +76,24 @@ function adder(xBin, yBin, carryIn, binSize) {
59
76
  }
60
77
  return res;
61
78
  }
62
- // Constant time addition.
79
+ /**
80
+ * Constant-time addition of two bigints, using 2's complement representation.
81
+ * @param x - The first operand.
82
+ * @param y - The second operand.
83
+ * @param binSize - The number of bits to use in the operation.
84
+ * @returns The sum as a bigint.
85
+ */
63
86
  function ctAdd(x, y, binSize) {
64
87
  const resBin = adder(toBinLE(x, binSize), toBinLE(y, binSize), false, binSize);
65
88
  return fromBinLE(resBin);
66
89
  }
67
- // Constant time subtraction.
90
+ /**
91
+ * Constant-time subtraction of two bigints, using 2's complement representation.
92
+ * @param x - The first operand.
93
+ * @param y - The second operand.
94
+ * @param binSize - The number of bits to use in the operation.
95
+ * @returns The difference as a bigint.
96
+ */
68
97
  function ctSub(x, y, binSize) {
69
98
  const yBin = toBinLE(y, binSize);
70
99
  const yBinNot = [];
@@ -74,23 +103,44 @@ function ctSub(x, y, binSize) {
74
103
  const resBin = adder(toBinLE(x, binSize), yBinNot, true, binSize);
75
104
  return fromBinLE(resBin);
76
105
  }
77
- // Constant time sign bit circuit.
106
+ /**
107
+ * Returns the sign bit of a bigint in constant time.
108
+ * @param x - The bigint to check.
109
+ * @param binSize - The bit position to check (typically the highest bit).
110
+ * @returns True if the sign bit is set, false otherwise.
111
+ */
78
112
  function ctSignBit(x, binSize) {
79
113
  return ((x >> binSize) & 1n) === 1n;
80
114
  }
81
- // Constant time less than circuit.
115
+ /**
116
+ * Constant-time less-than comparison for two bigints.
117
+ * @param x - The first operand.
118
+ * @param y - The second operand.
119
+ * @param binSize - The number of bits to use in the operation.
120
+ * @returns True if x < y, false otherwise.
121
+ */
82
122
  function ctLt(x, y, binSize) {
83
123
  return ctSignBit(ctSub(x, y, binSize), binSize);
84
124
  }
85
- // Constant time select.
125
+ /**
126
+ * Constant-time select between two bigints based on a boolean condition.
127
+ * @param b - The condition; if true, select x, otherwise select y.
128
+ * @param x - The value to select if b is true.
129
+ * @param y - The value to select if b is false.
130
+ * @param binSize - The number of bits to use in the operation.
131
+ * @returns The selected bigint.
132
+ */
86
133
  function ctSelect(b, x, y, binSize) {
87
134
  return ctAdd(y, BigInt(b) * (ctSub(x, y, binSize)), binSize);
88
135
  }
89
- // This function returns `true` if -2^binSize <= x < 2^binSize, and `false` otherwise.
90
- // The function is not constant-time for arbitrary x, but it is so for all inputs
91
- // for which the function returns `true`. If you assert your inputs to satisfy
92
- // verifyBinSize(x, binSize), then you need not care about the non constant-timeness
93
- // of this function.
136
+ /**
137
+ * Checks if a bigint fits in the range -2^binSize <= x < 2^binSize.
138
+ * Not constant-time for arbitrary x, but is constant-time for all inputs for which the function returns true.
139
+ * If you assert your inputs satisfy verifyBinSize(x, binSize), you need not care about the non constant-timeness of this function.
140
+ * @param x - The bigint to check.
141
+ * @param binSize - The number of bits to use in the check.
142
+ * @returns True if x fits in the range, false otherwise.
143
+ */
94
144
  function verifyBinSize(x, binSize) {
95
145
  const bin = (x >> binSize).toString(2);
96
146
  return bin === '0' || bin === '-1';
@@ -278,10 +328,17 @@ function randMatrix(field, nrows, ncols) {
278
328
  return new Matrix(field, data);
279
329
  }
280
330
 
331
+ /**
332
+ * Curve25519 base field as an IField instance.
333
+ */
281
334
  const CURVE25519_BASE_FIELD = ed25519.ed25519.CURVE.Fp;
282
335
  // hardcode security level to 128 bits
283
336
  const SECURITY_LEVEL = 128;
284
337
  // We refer to https://tosc.iacr.org/index.php/ToSC/article/view/8695/8287 for more details.
338
+ /**
339
+ * Description and parameters for the Rescue cipher or hash function, including round constants, MDS matrix, and key schedule.
340
+ * See: https://tosc.iacr.org/index.php/ToSC/article/view/8695/8287
341
+ */
285
342
  class RescueDesc {
286
343
  mode;
287
344
  field;
@@ -297,6 +354,12 @@ class RescueDesc {
297
354
  mdsMatInverse;
298
355
  // The round keys, needed for encryption and decryption.
299
356
  roundKeys;
357
+ /**
358
+ * Constructs a RescueDesc for a given field and mode (cipher or hash).
359
+ * Initializes round constants, MDS matrix, and key schedule.
360
+ * @param field - The field to use (e.g., CURVE25519_BASE_FIELD).
361
+ * @param mode - The mode: block cipher or hash function.
362
+ */
300
363
  constructor(field, mode) {
301
364
  this.field = field;
302
365
  this.mode = mode;
@@ -342,6 +405,11 @@ class RescueDesc {
342
405
  }
343
406
  }
344
407
  }
408
+ /**
409
+ * Samples round constants for the Rescue permutation, using SHAKE256.
410
+ * @param nRounds - The number of rounds.
411
+ * @returns An array of round constant matrices.
412
+ */
345
413
  sampleConstants(nRounds) {
346
414
  const field = this.field;
347
415
  const m = this.m;
@@ -415,9 +483,19 @@ class RescueDesc {
415
483
  default: return [];
416
484
  }
417
485
  }
486
+ /**
487
+ * Applies the Rescue permutation to a state matrix.
488
+ * @param state - The input state matrix.
489
+ * @returns The permuted state matrix.
490
+ */
418
491
  permute(state) {
419
492
  return rescuePermutation(this.mode, this.alpha, this.alphaInverse, this.mdsMat, this.roundKeys, state)[2 * this.nRounds];
420
493
  }
494
+ /**
495
+ * Applies the inverse Rescue permutation to a state matrix.
496
+ * @param state - The input state matrix.
497
+ * @returns The inverse-permuted state matrix.
498
+ */
421
499
  permuteInverse(state) {
422
500
  return rescuePermutationInverse(this.mode, this.alpha, this.alphaInverse, this.mdsMatInverse, this.roundKeys, state)[2 * this.nRounds];
423
501
  }
@@ -589,7 +667,17 @@ function toVec(data) {
589
667
  return dataVec;
590
668
  }
591
669
 
670
+ /**
671
+ * Number of mantissa bits for double-precision floating point values.
672
+ */
592
673
  const DOUBLE_PRECISION_MANTISSA = 52;
674
+ /**
675
+ * Encodes a value as a bigint suitable for Rescue encryption, handling booleans, bigints, and numbers.
676
+ * The encoding is performed in constant-time to avoid leaking information through timing side-channels.
677
+ * Throws if the value is out of the supported range for the field.
678
+ * @param v - The value to encode (MScalar, MFloat, or MBoolean).
679
+ * @returns The encoded value as a bigint.
680
+ */
593
681
  function encodeAsRescueEncryptable(v) {
594
682
  if (typeof v === 'boolean') {
595
683
  return v ? 1n : 0n;
@@ -618,6 +706,13 @@ function encodeAsRescueEncryptable(v) {
618
706
  // but typescript kept thinking ixInput: readonly null[] and I can't figure out why, so we do this hack
619
707
  // for now.
620
708
  // TODO: Revisit and fix the types correctly.
709
+ /**
710
+ * Secret-shares the inputs for a confidential instruction, encoding each value as needed and splitting it for each node's public key.
711
+ * @param ixInput - The array of input values to secret-share.
712
+ * @param nodeX25519Keys - The array of node X25519 public keys to share with.
713
+ * @returns A 2D array of SecretShare objects, one array per input value.
714
+ * @throws Error if an input type cannot be parsed.
715
+ */
621
716
  function secretShareInputs(ixInput, nodeX25519Keys) {
622
717
  const shares = [];
623
718
  // Need to explicitly tell typescript input can be any of these, else it only thinks {} is possible
@@ -669,9 +764,16 @@ function getBinSize(max) {
669
764
  return BigInt(Math.floor(Math.log2(Number(max)))) + 3n;
670
765
  }
671
766
 
672
- // Scalar field prime modulus 2^252 + 27742317777372353535851937790883648493
767
+ /**
768
+ * Scalar field prime modulus for Curve25519: 2^252 + 27742317777372353535851937790883648493
769
+ */
673
770
  const CURVE25519_SCALAR_FIELD_MODULUS = ed25519.ed25519.CURVE.n;
674
- // High level function for encrypting a value into the format the da layer expects
771
+ /**
772
+ * Encrypts a value into the format expected by the DA layer, using secret sharing and encryption for each node's public key.
773
+ * @param val - The value to secret-share and encrypt.
774
+ * @param nodeX25519Keys - The array of node X25519 public keys.
775
+ * @returns An array of SecretShare objects, one for each node.
776
+ */
675
777
  function secretShareValue(val, nodeX25519Keys) {
676
778
  const rawShares = genRawShares(val, nodeX25519Keys.length, CURVE25519_SCALAR_FIELD_MODULUS);
677
779
  return zip(rawShares, nodeX25519Keys).map(([share, key]) => encryptForDA(key, share, CURVE25519_SCALAR_FIELD_MODULUS));
@@ -690,10 +792,10 @@ function newSecretShare(ciphertext, nonce, ephemeralPublicKey) {
690
792
  }
691
793
  /**
692
794
  * Generates secret shares for a given value in the Curve25519 field.
693
- * @param secret The secret value to be shared (as a BigInt)
694
- * @param n The number of shares to generate
695
- * @param mod The modulo of the field over which to generate shares
696
- * @returns An array of n secret shares
795
+ * @param secret - The secret value to be shared (as a BigInt).
796
+ * @param n - The number of shares to generate.
797
+ * @param mod - The modulo of the field over which to generate shares (default: CURVE25519_SCALAR_FIELD_MODULUS).
798
+ * @returns An array of n secret shares as bigints.
697
799
  */
698
800
  function genRawShares(secret, n, mod = CURVE25519_SCALAR_FIELD_MODULUS) {
699
801
  const shares = [];
@@ -709,11 +811,11 @@ function genRawShares(secret, n, mod = CURVE25519_SCALAR_FIELD_MODULUS) {
709
811
  }
710
812
  /// ENCRYPTION
711
813
  /**
712
- * Encrypts a field element for the DA layer.
713
- * @param publicKey The recipient's x25519 public key
714
- * @param valueToEncrypt The bigint value to encrypt
715
- * @param modulo Bound on the value
716
- * @returns An object containing the ciphertext and ephemeral public key. Always pads to 32 bytes.
814
+ * Encrypts a field element for the DA layer using the recipient's x25519 public key.
815
+ * @param publicKey - The recipient's x25519 public key.
816
+ * @param valueToEncrypt - The bigint value to encrypt.
817
+ * @param modulo - Bound on the value (default: CURVE25519_SCALAR_FIELD_MODULUS).
818
+ * @returns An object containing the ciphertext, nonce, and ephemeral public key.
717
819
  */
718
820
  function encryptForDA(publicKey, valueToEncrypt, modulo = CURVE25519_SCALAR_FIELD_MODULUS) {
719
821
  // Check if the value to encrypt is smaller than the modulo
@@ -729,6 +831,12 @@ function encryptForDA(publicKey, valueToEncrypt, modulo = CURVE25519_SCALAR_FIEL
729
831
  const { ciphertext, nonce } = aesCtrEncrypt(valueToEncrypt, sharedSecret);
730
832
  return newSecretShare(ciphertext, nonce, ephemeralPublicKey);
731
833
  }
834
+ /**
835
+ * Computes a shared encryption key using ECDH (x25519) and hashes it with blake2s.
836
+ * @param privKey - The private key as a Uint8Array.
837
+ * @param pubKey - The public key as a Uint8Array.
838
+ * @returns The derived encryption key as a Uint8Array.
839
+ */
732
840
  function getEncryptionKey(privKey, pubKey) {
733
841
  const sharedSecret = ed25519.x25519.getSharedSecret(privKey, pubKey);
734
842
  return blake2s.blake2s(sharedSecret);
@@ -762,9 +870,10 @@ function aesCtrEncrypt(val, key) {
762
870
  }
763
871
  /// HELPERS
764
872
  /**
765
- * Generates a random val within the field bound by q.
873
+ * Generates a random value within the field bound by q.
874
+ * @param q - The upper bound (exclusive) for the random value.
766
875
  * @returns A random bigint value between 0 and q-1.
767
- */
876
+ */
768
877
  function generateRandomFieldElem(q) {
769
878
  const byteLength = (q.toString(2).length + 7) >> 3;
770
879
  let r;
@@ -774,10 +883,22 @@ function generateRandomFieldElem(q) {
774
883
  } while (r >= q);
775
884
  return r;
776
885
  }
777
- // Helper function for positive modulo
886
+ /**
887
+ * Computes the positive modulo of a over m.
888
+ * @param a - The dividend.
889
+ * @param m - The modulus.
890
+ * @returns The positive remainder of a mod m.
891
+ */
778
892
  function positiveModulo(a, m) {
779
893
  return ((a % m) + m) % m;
780
894
  }
895
+ /**
896
+ * Serializes a bigint to a little-endian Uint8Array of the specified length.
897
+ * @param val - The bigint value to serialize.
898
+ * @param lengthInBytes - The desired length of the output array.
899
+ * @returns The serialized value as a Uint8Array.
900
+ * @throws Error if the value is too large for the specified length.
901
+ */
781
902
  function serializeLE(val, lengthInBytes) {
782
903
  const result = new Uint8Array(lengthInBytes);
783
904
  let tempVal = val;
@@ -790,6 +911,11 @@ function serializeLE(val, lengthInBytes) {
790
911
  }
791
912
  return result;
792
913
  }
914
+ /**
915
+ * Deserializes a little-endian Uint8Array to a bigint.
916
+ * @param bytes - The Uint8Array to deserialize.
917
+ * @returns The deserialized bigint value.
918
+ */
793
919
  function deserializeLE(bytes) {
794
920
  let result = BigInt(0);
795
921
  for (let i = 0; i < bytes.length; i++) {
@@ -798,6 +924,11 @@ function deserializeLE(bytes) {
798
924
  return result;
799
925
  }
800
926
  // GENERAL
927
+ /**
928
+ * Computes the SHA-256 hash of an array of Uint8Arrays.
929
+ * @param byteArrays - The arrays to hash.
930
+ * @returns The SHA-256 hash as a Buffer.
931
+ */
801
932
  function sha256(byteArrays) {
802
933
  const hash = crypto.createHash('sha256');
803
934
  byteArrays.forEach((byteArray) => {
@@ -806,19 +937,28 @@ function sha256(byteArrays) {
806
937
  return hash.digest();
807
938
  }
808
939
 
809
- /// The Rescue-Prime hash funtion, see https://eprint.iacr.org/2020/1143.pdf.
810
- /// We use it with fixed m = 6 and capacity = 1, hence rate = 5. According to Section 2.2, this
811
- /// offers log2(CURVE25519_BASE_FIELD.ORDER) / 2 bits of security against collision, preimage and
812
- /// second-preimage attacks.
940
+ /**
941
+ * The Rescue-Prime hash function, as described in https://eprint.iacr.org/2020/1143.pdf.
942
+ * 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.
943
+ * See the referenced paper for further details.
944
+ */
813
945
  class RescuePrimeHash {
814
946
  desc;
815
947
  rate;
948
+ /**
949
+ * Constructs a RescuePrimeHash instance with m = 6 and capacity = 1.
950
+ */
816
951
  constructor() {
817
952
  this.desc = new RescueDesc(CURVE25519_BASE_FIELD, { kind: 'hash', m: 6, capacity: 1 });
818
953
  this.rate = 6 - 1;
819
954
  }
820
955
  // This is Algorithm 1 from https://eprint.iacr.org/2020/1143.pdf, though with the padding (see Algorithm 2).
821
956
  // The hash function outputs this.rate elements.
957
+ /**
958
+ * Computes the Rescue-Prime hash of a message, with padding as described in Algorithm 2 of the paper.
959
+ * @param message - The input message as an array of bigints.
960
+ * @returns The hash output as an array of bigints (length = rate).
961
+ */
822
962
  digest(message) {
823
963
  message.push(1n);
824
964
  while (message.length % this.rate !== 0) {
@@ -848,21 +988,33 @@ class RescuePrimeHash {
848
988
  }
849
989
  }
850
990
 
851
- /// The HMAC-Rescue-Prime function. Since Rescue-Prime is based on the sponge construction,
852
- /// the traditional HMAC can be replaced by the simpler MAC, see e.g.
853
- /// https://keccak.team/files/SpongeFunctions.pdf (Appendix B) or
854
- /// https://keccak.team/keccak_strengths.html.
991
+ /**
992
+ * HMACRescuePrime provides a message authentication code (MAC) using the Rescue-Prime hash function.
993
+ * Rescue-Prime is based on the sponge construction, which allows the use of a simpler MAC in place of the traditional HMAC.
994
+ * For more details and explanations, see: https://keccak.team/files/SpongeFunctions.pdf (Appendix B) or https://keccak.team/keccak_strengths.html.
995
+ */
855
996
  class HMACRescuePrime {
856
997
  hasher;
998
+ /**
999
+ * Constructs a new HMACRescuePrime instance.
1000
+ */
857
1001
  constructor() {
858
1002
  this.hasher = new RescuePrimeHash();
859
1003
  }
1004
+ /**
1005
+ * Computes the HMAC (or MAC) digest of a message with a given key using Rescue-Prime.
1006
+ * The key is padded to the hash function's rate, then concatenated with the message.
1007
+ * @param key - The key as an array of bigints.
1008
+ * @param message - The message as an array of bigints.
1009
+ * @returns The MAC digest as an array of bigints.
1010
+ * @throws Error if the key is longer than the hash function's rate.
1011
+ */
860
1012
  digest(key, message) {
861
1013
  // HMAC-digest(key, message) = hasher.digest(key || message), since Rescue-Prime is based on
862
1014
  // the sponge construction.
863
1015
  // We follow https://datatracker.ietf.org/doc/html/rfc2104, though since Rescue-Prime is not based
864
1016
  // on the Merkle-Damgard construction we cannot have an exact anology between the
865
- // parameters. For our purpose, we set B = L = hasher.rate().
1017
+ // parameters. For our purpose, we set B = L = hasher.rate.
866
1018
  if (key.length > this.hasher.rate) {
867
1019
  throw Error(`length of key is supposed to be at most the hash function's rate (found ${key.length} and ${this.hasher.rate})`);
868
1020
  }
@@ -875,39 +1027,82 @@ class HMACRescuePrime {
875
1027
  }
876
1028
  }
877
1029
 
878
- /// The HMAC-Rescue-Prime function. Since Rescue-Prime is based on the sponge construction,
879
- /// the traditional HMAC can be replaced by the simpler MAC, see e.g.
880
- /// https://keccak.team/files/SpongeFunctions.pdf (Appendix B) or
881
- /// https://keccak.team/keccak_strengths.html.
1030
+ /**
1031
+ * HKDF (HMAC-based Extract-and-Expand Key Derivation Function) using the Rescue-Prime hash function.
1032
+ * Follows RFC 5869. Only supports L = HashLen.
1033
+ */
882
1034
  class HKDFRescuePrime {
883
1035
  hmac;
1036
+ /**
1037
+ * Constructs a new HKDFRescuePrime instance.
1038
+ */
884
1039
  constructor() {
885
1040
  this.hmac = new HMACRescuePrime();
886
1041
  }
1042
+ /**
1043
+ * HKDF-Extract step: derives a pseudorandom key (PRK) from the input keying material (IKM) and salt.
1044
+ * @param salt - The salt value as an array of bigints.
1045
+ * @param ikm - The input keying material as an array of bigints.
1046
+ * @returns The pseudorandom key (PRK) as an array of bigints.
1047
+ */
887
1048
  extract(salt, ikm) {
1049
+ if (salt.length === 0) {
1050
+ // HashLen = hasher.rate for Rescue-Prime
1051
+ for (let i = 0; i < this.hmac.hasher.rate; ++i) {
1052
+ salt.push(0n);
1053
+ }
1054
+ }
888
1055
  return this.hmac.digest(salt, ikm);
889
1056
  }
1057
+ /**
1058
+ * HKDF-Expand step: expands the pseudorandom key (PRK) with info to produce output keying material (OKM).
1059
+ * Only supports L = HashLen = 5, i.e. N = 1.
1060
+ * @param prk - The pseudorandom key as an array of bigints.
1061
+ * @param info - The context and application specific information as an array of bigints.
1062
+ * @returns The output keying material (OKM) as an array of bigints.
1063
+ */
890
1064
  expand(prk, info) {
891
- // we go with L = HashLen = 5, i.e. N = 1
1065
+ // we only support L = HashLen = 5, i.e. N = 1
1066
+ // message = empty string | info | 0x01
892
1067
  info.push(1n);
893
1068
  return this.hmac.digest(prk, info);
894
1069
  }
1070
+ /**
1071
+ * Performs the full HKDF (extract and expand) to derive output keying material (OKM).
1072
+ * @param salt - The salt value as an array of bigints.
1073
+ * @param ikm - The input keying material as an array of bigints.
1074
+ * @param info - The context and application specific information as an array of bigints.
1075
+ * @returns The output keying material (OKM) as an array of bigints.
1076
+ */
895
1077
  okm(salt, ikm, info) {
896
1078
  const prk = this.extract(salt, ikm);
897
1079
  return this.expand(prk, info);
898
1080
  }
899
1081
  }
900
1082
 
901
- /// The Rescue cipher, see https://tosc.iacr.org/index.php/ToSC/article/view/8695/8287.
902
- /// We use it in Counter (CTR) mode, with a fixed m = 5.
1083
+ /**
1084
+ * The Rescue cipher in Counter (CTR) mode, with a fixed block size m = 5.
1085
+ * See: https://tosc.iacr.org/index.php/ToSC/article/view/8695/8287
1086
+ */
903
1087
  class RescueCipher {
904
1088
  desc;
1089
+ /**
1090
+ * Constructs a RescueCipher instance using a shared secret.
1091
+ * The key is derived using HKDF-RescuePrime and used to initialize the RescueDesc.
1092
+ * @param sharedSecret - The shared secret to derive the cipher key from.
1093
+ */
905
1094
  constructor(sharedSecret) {
906
1095
  const hkdf = new HKDFRescuePrime();
907
- const rescueKey = hkdf.okm([0n, 0n, 0n, 0n, 0n], [deserializeLE(sharedSecret)], [0n]);
1096
+ const rescueKey = hkdf.okm([], [deserializeLE(sharedSecret)], []);
908
1097
  this.desc = new RescueDesc(CURVE25519_BASE_FIELD, { kind: 'cipher', key: rescueKey });
909
1098
  }
910
- /// Encrypt the plaintext vector in Counter (CTR) mode.
1099
+ /**
1100
+ * Encrypts the plaintext vector in Counter (CTR) mode (raw, returns bigints).
1101
+ * @param plaintext - The array of plaintext bigints to encrypt.
1102
+ * @param nonce - A 16-byte nonce for CTR mode.
1103
+ * @returns The ciphertext as an array of bigints.
1104
+ * @throws Error if the nonce is not 16 bytes long.
1105
+ */
911
1106
  encrypt_raw(plaintext, nonce) {
912
1107
  if (nonce.length !== 16) {
913
1108
  throw Error(`nonce must be of length 16 (found ${nonce.length})`);
@@ -940,11 +1135,22 @@ class RescueCipher {
940
1135
  }
941
1136
  return ciphertext;
942
1137
  }
943
- /// Encrypt the plaintext vector in Counter (CTR) mode and serialize.
1138
+ /**
1139
+ * Encrypts the plaintext vector in Counter (CTR) mode and serializes each block.
1140
+ * @param plaintext - The array of plaintext bigints to encrypt.
1141
+ * @param nonce - A 16-byte nonce for CTR mode.
1142
+ * @returns The ciphertext as an array of arrays of numbers (each 32 bytes).
1143
+ */
944
1144
  encrypt(plaintext, nonce) {
945
1145
  return this.encrypt_raw(plaintext, nonce).map((c) => Array.from(serializeLE(c, 32)));
946
1146
  }
947
- /// Decrypt the ciphertext vector in Counter (CTR) mode.
1147
+ /**
1148
+ * Decrypts the ciphertext vector in Counter (CTR) mode (raw, expects bigints).
1149
+ * @param ciphertext - The array of ciphertext bigints to decrypt.
1150
+ * @param nonce - A 16-byte nonce for CTR mode.
1151
+ * @returns The decrypted plaintext as an array of bigints.
1152
+ * @throws Error if the nonce is not 16 bytes long.
1153
+ */
948
1154
  decrypt_raw(ciphertext, nonce) {
949
1155
  if (nonce.length !== 16) {
950
1156
  throw Error(`nonce must be of length 16 (found ${nonce.length})`);
@@ -974,7 +1180,12 @@ class RescueCipher {
974
1180
  }
975
1181
  return decrypted;
976
1182
  }
977
- /// Deserialize and decrypt the ciphertext vector in Counter (CTR) mode
1183
+ /**
1184
+ * Deserializes and decrypts the ciphertext vector in Counter (CTR) mode.
1185
+ * @param ciphertext - The array of arrays of numbers (each 32 bytes) to decrypt.
1186
+ * @param nonce - A 16-byte nonce for CTR mode.
1187
+ * @returns The decrypted plaintext as an array of bigints.
1188
+ */
978
1189
  decrypt(ciphertext, nonce) {
979
1190
  return this.decrypt_raw(ciphertext.map((c) => {
980
1191
  if (c.length !== 32) {
@@ -984,6 +1195,12 @@ class RescueCipher {
984
1195
  }), nonce);
985
1196
  }
986
1197
  }
1198
+ /**
1199
+ * Generates the counter values for Rescue cipher CTR mode.
1200
+ * @param nonce - The initial nonce as a bigint.
1201
+ * @param nBlocks - The number of blocks to generate counters for.
1202
+ * @returns An array of counter values as bigints.
1203
+ */
987
1204
  function getCounter(nonce, nBlocks) {
988
1205
  const counter = [];
989
1206
  for (let i = 0n; i < nBlocks; ++i) {
@@ -996,10 +1213,203 @@ function getCounter(nonce, nBlocks) {
996
1213
  return counter;
997
1214
  }
998
1215
 
1216
+ // The arcisEd25519 signature scheme. This is essentially ed25519 but we use the hash function
1217
+ // SHA3-512 instead of SHA-512 since its multiplicative depth is much lower, which
1218
+ // makes it much better suited to be evaluated in MPC.
1219
+ // Those are the parameters specified [here](https://datatracker.ietf.org/doc/html/rfc8032#section-5.1)
1220
+ // (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).
1221
+ const arcisEd25519Defaults = (() => ({
1222
+ a: BigInt(-1),
1223
+ d: BigInt('37095705934669439343138083508754565189542113879843219016388785533085940283555'),
1224
+ Fp: ed25519.ed25519.CURVE.Fp,
1225
+ n: BigInt('7237005577332262213973186563042994240857116359379907606001950938285454250989'),
1226
+ h: BigInt(8),
1227
+ Gx: BigInt('15112221349535400772501151409588531511454012693041857206046113283949847762202'),
1228
+ Gy: BigInt('46316835694926478169428394003475163141307993866256225615783033603165251855960'),
1229
+ hash: sha3.sha3_512,
1230
+ randomBytes: utils.randomBytes,
1231
+ adjustScalarBytes,
1232
+ uvRatio,
1233
+ }))();
1234
+ /**
1235
+ * Clamps a 32-byte scalar as required by the Ed25519 signature scheme.
1236
+ * See: https://datatracker.ietf.org/doc/html/rfc8032#section-5.1.5
1237
+ * @param bytes - The 32-byte scalar to clamp.
1238
+ * @returns The clamped scalar as a Uint8Array.
1239
+ */
1240
+ function adjustScalarBytes(bytes) {
1241
+ const clamped = bytes;
1242
+ clamped[0] &= 248;
1243
+ clamped[31] &= 127;
1244
+ clamped[31] |= 64;
1245
+ return clamped;
1246
+ }
1247
+ /**
1248
+ * Dummy function for compatibility; not used in the ArcisEd25519 signature scheme.
1249
+ * Always returns { isValid: true, value: 0n }.
1250
+ * @returns An object with isValid: true and value: 0n.
1251
+ */
1252
+ function uvRatio() {
1253
+ return { isValid: true, value: 0n };
1254
+ }
1255
+ /**
1256
+ * Ed25519 curve instance using SHA3-512 for hashing, suitable for MPC (ArcisEd25519 signature scheme).
1257
+ * This is essentially Ed25519 but with SHA3-512 instead of SHA-512 for lower multiplicative depth.
1258
+ * See: https://datatracker.ietf.org/doc/html/rfc8032#section-5.1
1259
+ */
1260
+ const arcisEd25519 = (() => edwards.twistedEdwards(arcisEd25519Defaults))();
1261
+
1262
+ /**
1263
+ * AES-128 cipher in Counter (CTR) mode, using HKDF-SHA3-256 to derive the key from a shared secret.
1264
+ * See: https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf (Section 6.5) for details on CTR mode.
1265
+ */
1266
+ class Aes128Cipher {
1267
+ key;
1268
+ /**
1269
+ * Constructs an AES-128 cipher instance using a shared secret.
1270
+ * The key is derived using HKDF-SHA3-256.
1271
+ * @param sharedSecret - The shared secret to derive the AES key from.
1272
+ */
1273
+ constructor(sharedSecret) {
1274
+ const aesKey = crypto.hkdfSync('sha3-256', sharedSecret, new Uint8Array(), new Uint8Array(), 16);
1275
+ this.key = new Uint8Array(aesKey);
1276
+ }
1277
+ /**
1278
+ * Encrypts the plaintext array in Counter (CTR) mode.
1279
+ * @param plaintext - The data to encrypt.
1280
+ * @param nonce - An 8-byte nonce for CTR mode.
1281
+ * @returns The encrypted ciphertext as a Uint8Array.
1282
+ * @throws Error if the nonce is not 8 bytes long.
1283
+ */
1284
+ encrypt(plaintext, nonce) {
1285
+ if (nonce.length !== 8) {
1286
+ throw Error(`nonce must be of length 8 (found ${nonce.length})`);
1287
+ }
1288
+ const paddedNonce = Buffer.concat([nonce, Buffer.alloc(16 - nonce.length, 0)]);
1289
+ const cipher = crypto.createCipheriv('aes-128-ctr', this.key, paddedNonce);
1290
+ const ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]);
1291
+ return new Uint8Array(ciphertext);
1292
+ }
1293
+ /**
1294
+ * Decrypts the ciphertext array in Counter (CTR) mode.
1295
+ * @param ciphertext - The data to decrypt.
1296
+ * @param nonce - An 8-byte nonce for CTR mode.
1297
+ * @returns The decrypted plaintext as a Uint8Array.
1298
+ * @throws Error if the nonce is not 8 bytes long.
1299
+ */
1300
+ decrypt(ciphertext, nonce) {
1301
+ if (nonce.length !== 8) {
1302
+ throw Error(`nonce must be of length 8 (found ${nonce.length})`);
1303
+ }
1304
+ const paddedNonce = Buffer.concat([nonce, Buffer.alloc(16 - nonce.length, 0)]);
1305
+ const cipher = crypto.createDecipheriv('aes-128-ctr', this.key, paddedNonce);
1306
+ const decrypted = Buffer.concat([cipher.update(ciphertext), cipher.final()]);
1307
+ return new Uint8Array(decrypted);
1308
+ }
1309
+ }
1310
+
1311
+ /**
1312
+ * AES-192 cipher in Counter (CTR) mode, using HKDF-SHA3-256 to derive the key from a shared secret.
1313
+ * See: https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf (Section 6.5) for details on CTR mode.
1314
+ */
1315
+ class Aes192Cipher {
1316
+ key;
1317
+ /**
1318
+ * Constructs an AES-192 cipher instance using a shared secret.
1319
+ * The key is derived using HKDF-SHA3-256.
1320
+ * @param sharedSecret - The shared secret to derive the AES key from.
1321
+ */
1322
+ constructor(sharedSecret) {
1323
+ const aesKey = crypto.hkdfSync('sha3-256', sharedSecret, new Uint8Array(), new Uint8Array(), 24);
1324
+ this.key = new Uint8Array(aesKey);
1325
+ }
1326
+ /**
1327
+ * Encrypts the plaintext array in Counter (CTR) mode.
1328
+ * @param plaintext - The data to encrypt.
1329
+ * @param nonce - An 8-byte nonce for CTR mode.
1330
+ * @returns The encrypted ciphertext as a Uint8Array.
1331
+ * @throws Error if the nonce is not 8 bytes long.
1332
+ */
1333
+ encrypt(plaintext, nonce) {
1334
+ if (nonce.length !== 8) {
1335
+ throw Error(`nonce must be of length 8 (found ${nonce.length})`);
1336
+ }
1337
+ const paddedNonce = Buffer.concat([nonce, Buffer.alloc(16 - nonce.length, 0)]);
1338
+ const cipher = crypto.createCipheriv('aes-192-ctr', this.key, paddedNonce);
1339
+ const ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]);
1340
+ return new Uint8Array(ciphertext);
1341
+ }
1342
+ /**
1343
+ * Decrypts the ciphertext array in Counter (CTR) mode.
1344
+ * @param ciphertext - The data to decrypt.
1345
+ * @param nonce - An 8-byte nonce for CTR mode.
1346
+ * @returns The decrypted plaintext as a Uint8Array.
1347
+ * @throws Error if the nonce is not 8 bytes long.
1348
+ */
1349
+ decrypt(ciphertext, nonce) {
1350
+ if (nonce.length !== 8) {
1351
+ throw Error(`nonce must be of length 8 (found ${nonce.length})`);
1352
+ }
1353
+ const paddedNonce = Buffer.concat([nonce, Buffer.alloc(16 - nonce.length, 0)]);
1354
+ const cipher = crypto.createDecipheriv('aes-192-ctr', this.key, paddedNonce);
1355
+ const decrypted = Buffer.concat([cipher.update(ciphertext), cipher.final()]);
1356
+ return new Uint8Array(decrypted);
1357
+ }
1358
+ }
1359
+
1360
+ /**
1361
+ * AES-256 cipher in Counter (CTR) mode, using HKDF-SHA3-256 to derive the key from a shared secret.
1362
+ * See: https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf (Section 6.5) for details on CTR mode.
1363
+ */
1364
+ class Aes256Cipher {
1365
+ key;
1366
+ /**
1367
+ * Constructs an AES-256 cipher instance using a shared secret.
1368
+ * The key is derived using HKDF-SHA3-256.
1369
+ * @param sharedSecret - The shared secret to derive the AES key from.
1370
+ */
1371
+ constructor(sharedSecret) {
1372
+ const aesKey = crypto.hkdfSync('sha3-256', sharedSecret, new Uint8Array(), new Uint8Array(), 32);
1373
+ this.key = new Uint8Array(aesKey);
1374
+ }
1375
+ /**
1376
+ * Encrypts the plaintext array in Counter (CTR) mode.
1377
+ * @param plaintext - The data to encrypt.
1378
+ * @param nonce - An 8-byte nonce for CTR mode.
1379
+ * @returns The encrypted ciphertext as a Uint8Array.
1380
+ * @throws Error if the nonce is not 8 bytes long.
1381
+ */
1382
+ encrypt(plaintext, nonce) {
1383
+ if (nonce.length !== 8) {
1384
+ throw Error(`nonce must be of length 8 (found ${nonce.length})`);
1385
+ }
1386
+ const paddedNonce = Buffer.concat([nonce, Buffer.alloc(16 - nonce.length, 0)]);
1387
+ const cipher = crypto.createCipheriv('aes-256-ctr', this.key, paddedNonce);
1388
+ const ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]);
1389
+ return new Uint8Array(ciphertext);
1390
+ }
1391
+ /**
1392
+ * Decrypts the ciphertext array in Counter (CTR) mode.
1393
+ * @param ciphertext - The data to decrypt.
1394
+ * @param nonce - An 8-byte nonce for CTR mode.
1395
+ * @returns The decrypted plaintext as a Uint8Array.
1396
+ * @throws Error if the nonce is not 8 bytes long.
1397
+ */
1398
+ decrypt(ciphertext, nonce) {
1399
+ if (nonce.length !== 8) {
1400
+ throw Error(`nonce must be of length 8 (found ${nonce.length})`);
1401
+ }
1402
+ const paddedNonce = Buffer.concat([nonce, Buffer.alloc(16 - nonce.length, 0)]);
1403
+ const cipher = crypto.createDecipheriv('aes-256-ctr', this.key, paddedNonce);
1404
+ const decrypted = Buffer.concat([cipher.update(ciphertext), cipher.final()]);
1405
+ return new Uint8Array(decrypted);
1406
+ }
1407
+ }
1408
+
999
1409
  var address = "BKck65TgoKRokMjQM3datB9oRwJ8rAj2jxPXvHXUvcL6";
1000
1410
  var metadata = {
1001
1411
  name: "arcium",
1002
- version: "0.1.46",
1412
+ version: "0.1.47",
1003
1413
  spec: "0.1.0",
1004
1414
  description: "The Arcium program"
1005
1415
  };
@@ -11541,32 +11951,75 @@ var ARCIUM_IDL = /*#__PURE__*/Object.freeze({
11541
11951
  types: types
11542
11952
  });
11543
11953
 
11954
+ /**
11955
+ * The deployed address of the Arcium program, as specified in the IDL.
11956
+ */
11544
11957
  const ARCIUM_ADDR = address;
11545
11958
 
11546
- // Seed for ClockAccount PDA
11959
+ /**
11960
+ * Seed for ClockAccount PDA
11961
+ * @constant {string}
11962
+ */
11547
11963
  const CLOCK_ACC_SEED = 'ClockAccount';
11548
- // Seed for StakingPoolAccount PDA
11964
+ /**
11965
+ * Seed for StakingPoolAccount PDA
11966
+ * @constant {string}
11967
+ */
11549
11968
  const POOL_ACC_SEED = 'StakingPoolAccount';
11550
- // Seed for ComputationAccount PDA
11969
+ /**
11970
+ * Seed for ComputationAccount PDA
11971
+ * @constant {string}
11972
+ */
11551
11973
  const COMPUTATION_ACC_SEED = 'ComputationAccount';
11552
- // Seed for Mempool PDA
11974
+ /**
11975
+ * Seed for Mempool PDA
11976
+ * @constant {string}
11977
+ */
11553
11978
  const MEMPOOL_ACC_SEED = 'Mempool';
11554
- // Seed for ExecutingPoolAccount PDA
11979
+ /**
11980
+ * Seed for ExecutingPoolAccount PDA
11981
+ * @constant {string}
11982
+ */
11555
11983
  const EXEC_POOL_ACC_SEED = 'Execpool';
11556
- // Seed for ClusterAccount PDA
11984
+ /**
11985
+ * Seed for ClusterAccount PDA
11986
+ * @constant {string}
11987
+ */
11557
11988
  const CLUSTER_ACC_SEED = 'Cluster';
11558
- // Seed for ArxNodeAccount PDA
11989
+ /**
11990
+ * Seed for ArxNodeAccount PDA
11991
+ * @constant {string}
11992
+ */
11559
11993
  const ARX_NODE_ACC_SEED = 'ArxNode';
11560
- // Seed for MXEAccAccount PDA
11994
+ /**
11995
+ * Seed for MXEAccAccount PDA
11996
+ * @constant {string}
11997
+ */
11561
11998
  const MXE_ACC_ACC_SEED = 'PersistentMXEAccount';
11562
- // Seed for CompDefAccount PDA
11999
+ /**
12000
+ * Seed for CompDefAccount PDA
12001
+ * @constant {string}
12002
+ */
11563
12003
  const COMP_DEF_ACC_SEED = 'ComputationDefinitionAccount';
12004
+ /**
12005
+ * Maximum number of bytes that can be reallocated per instruction.
12006
+ * @constant {number}
12007
+ */
11564
12008
  const MAX_REALLOC_PER_IX = 10240;
11565
- // Max number of bytes we can upload in a single transaction with the upload instruction
12009
+ /**
12010
+ * Maximum number of bytes that can be uploaded in a single transaction with the upload instruction.
12011
+ * @constant {number}
12012
+ */
11566
12013
  const MAX_UPLOAD_PER_TX_BYTES = 814;
11567
- // Max size of an account in bytes
11568
- const MAX_ACCOUNT_SIZE = 10485760; // 10MB = 10 * 1024 * 1024
11569
- // Max number of arcium embiggen instructions we can have in a single transaction (due to CUs)
12014
+ /**
12015
+ * Maximum size of an account in bytes (10MB = 10 * 1024 * 1024).
12016
+ * @constant {number}
12017
+ */
12018
+ const MAX_ACCOUNT_SIZE = 10485760;
12019
+ /**
12020
+ * Maximum number of arcium embiggen instructions allowed in a single transaction (due to compute unit limits).
12021
+ * @constant {number}
12022
+ */
11570
12023
  const MAX_EMBIGGEN_IX_PER_TX = 18;
11571
12024
 
11572
12025
  const TINY_MEMPOOL_ACC_NAME = 'tinyMempool';
@@ -11669,9 +12122,19 @@ const EXECPOOL_DISCRIMINATOR_MAP = {
11669
12122
  [MEDIUM_EXECPOOL_DISCRIMINATOR.toString()]: MEDIUM_EXECPOOL_ACC_NAME,
11670
12123
  [LARGE_EXECPOOL_DISCRIMINATOR.toString()]: LARGE_EXECPOOL_ACC_NAME,
11671
12124
  };
12125
+ /**
12126
+ * Returns the public key of the deployed Arcium program on Solana.
12127
+ * @returns The Arcium program's public key.
12128
+ */
11672
12129
  function getArciumProgAddress() {
11673
12130
  return new anchor__namespace.web3.PublicKey(ARCIUM_ADDR);
11674
12131
  }
12132
+ /**
12133
+ * Fetches the DA (Data Availability) info for all nodes in a cluster.
12134
+ * @param provider - The Anchor provider to use for fetching accounts.
12135
+ * @param clusterAddr - The public key of the cluster account.
12136
+ * @returns An array of NodeDAInfo objects for each node in the cluster.
12137
+ */
11675
12138
  async function getClusterDAInfo(provider, clusterAddr) {
11676
12139
  const program = getArciumProgram(provider);
11677
12140
  const clusterAcc = await program.account.cluster.fetch(clusterAddr);
@@ -11682,6 +12145,13 @@ async function getClusterDAInfo(provider, clusterAddr) {
11682
12145
  return { solanaPubkey: nodeAccPubkey, x25519Pubkey: Uint8Array.from(nodeAcc.encryptionPubkey) };
11683
12146
  }));
11684
12147
  }
12148
+ /**
12149
+ * Fetches and decodes the mempool account data for any mempool account size.
12150
+ * @param provider - The Anchor provider to use for fetching accounts.
12151
+ * @param mempoolAccPubkey - The public key of the mempool account.
12152
+ * @returns The decoded mempool account data.
12153
+ * @throws Error if the account cannot be fetched or the discriminator is unknown.
12154
+ */
11685
12155
  async function getMempoolAccData(provider, mempoolAccPubkey) {
11686
12156
  const accData = await provider.connection.getAccountInfo(mempoolAccPubkey);
11687
12157
  if (accData === null) {
@@ -11695,6 +12165,13 @@ async function getMempoolAccData(provider, mempoolAccPubkey) {
11695
12165
  const program = getArciumProgram(provider);
11696
12166
  return program.coder.accounts.decode(accName, accData.data);
11697
12167
  }
12168
+ /**
12169
+ * Fetches and decodes the executing pool account data for any pool size.
12170
+ * @param provider - The Anchor provider to use for fetching accounts.
12171
+ * @param executingPoolAccPubkey - The public key of the executing pool account.
12172
+ * @returns The decoded executing pool account data.
12173
+ * @throws Error if the account cannot be fetched or the discriminator is unknown.
12174
+ */
11698
12175
  async function getExecutingPoolAccData(provider, executingPoolAccPubkey) {
11699
12176
  const accData = await provider.connection.getAccountInfo(executingPoolAccPubkey);
11700
12177
  if (accData === null) {
@@ -11708,6 +12185,16 @@ async function getExecutingPoolAccData(provider, executingPoolAccPubkey) {
11708
12185
  const program = getArciumProgram(provider);
11709
12186
  return program.coder.accounts.decode(accName, accData.data);
11710
12187
  }
12188
+ /**
12189
+ * Uploads a circuit to the blockchain, splitting it into multiple accounts if necessary.
12190
+ * @param provider - The Anchor provider to use for transactions.
12191
+ * @param circuitName - The name of the circuit.
12192
+ * @param mxeProgramID - The public key of the MXE program.
12193
+ * @param rawCircuit - The raw circuit data as a Uint8Array.
12194
+ * @param logging - Whether to log progress (default: true).
12195
+ * @param chunkSize - The number of upload transactions to send in parallel (default: 500).
12196
+ * @returns An array of transaction signatures for all upload and finalize transactions.
12197
+ */
11711
12198
  async function uploadCircuit(provider, circuitName, mxeProgramID, rawCircuit, logging = true, chunkSize = 500) {
11712
12199
  const numAccs = Math.ceil(rawCircuit.length / (MAX_ACCOUNT_SIZE - 9));
11713
12200
  const compDefAccInfo = getCompDefAccInfo(circuitName, mxeProgramID);
@@ -11722,6 +12209,13 @@ async function uploadCircuit(provider, circuitName, mxeProgramID, rawCircuit, lo
11722
12209
  sigs.push(await signAndSendWithBlockhash(provider, finalizeCompDefTx, await provider.connection.getLatestBlockhash()));
11723
12210
  return sigs;
11724
12211
  }
12212
+ /**
12213
+ * Builds a transaction to finalize a computation definition.
12214
+ * @param provider - The Anchor provider to use for transactions.
12215
+ * @param compDefOffset - The offset of the computation definition.
12216
+ * @param mxeProgramID - The public key of the MXE program.
12217
+ * @returns The transaction to finalize the computation definition.
12218
+ */
11725
12219
  async function buildFinalizeCompDefTx(provider, compDefOffset, mxeProgramID) {
11726
12220
  const program = getArciumProgram(provider);
11727
12221
  const compDefOffsetBuffer = Buffer.alloc(4);
@@ -11823,35 +12317,78 @@ async function signAndSendWithBlockhash(provider, tx, block) {
11823
12317
  tx.lastValidBlockHeight = block.lastValidBlockHeight;
11824
12318
  return provider.sendAndConfirm(tx, [], { commitment: 'confirmed' });
11825
12319
  }
12320
+ /**
12321
+ * Returns the base seed for an Arcium account, given its name.
12322
+ * @param accName - The name of the account.
12323
+ * @returns The base seed as a Uint8Array.
12324
+ */
11826
12325
  function getArciumAccountBaseSeed(accName) {
11827
12326
  return Buffer.from(accName, 'utf-8');
11828
12327
  }
12328
+ /**
12329
+ * Computes the offset for a computation definition account, based on the circuit name.
12330
+ * @param circuitName - The name of the circuit.
12331
+ * @returns The offset as a 4-byte Uint8Array.
12332
+ */
11829
12333
  function getCompDefAccOffset(circuitName) {
11830
12334
  const hash = new Uint8Array(sha256([Buffer.from(circuitName, 'utf-8')]));
11831
12335
  return hash.slice(0, 4);
11832
12336
  }
12337
+ /**
12338
+ * Returns an Anchor program instance for the Arcium program.
12339
+ * @param provider - The Anchor provider to use.
12340
+ * @returns The Anchor program instance for Arcium.
12341
+ */
11833
12342
  function getArciumProgram(provider) {
11834
12343
  return new anchor.Program(ARCIUM_IDL, provider);
11835
12344
  }
12345
+ /**
12346
+ * Returns a read-only Anchor program instance for the Arcium program.
12347
+ * @param provider - The Anchor provider to use.
12348
+ * @returns The Anchor program instance for Arcium.
12349
+ */
11836
12350
  function getArciumProgramReadonly(provider) {
11837
12351
  return new anchor.Program(ARCIUM_IDL, provider);
11838
12352
  }
12353
+ /**
12354
+ * Returns the PDA (program-derived address) for an ArxNode account given the program ID and node offset.
12355
+ * @param arciumProgramID - The public key of the Arcium program.
12356
+ * @param nodeOffset - The offset of the node.
12357
+ * @returns The PDA for the ArxNode account.
12358
+ */
11839
12359
  function getArxAccPDA(arciumProgramID, nodeOffset) {
11840
12360
  const nodeOffsetBuffer = Buffer.alloc(4);
11841
12361
  nodeOffsetBuffer.writeUInt32LE(nodeOffset, 0);
11842
12362
  return anchor__namespace.web3.PublicKey.findProgramAddressSync([Buffer.from('ArxNode', 'utf-8'), nodeOffsetBuffer], arciumProgramID)[0];
11843
12363
  }
12364
+ /**
12365
+ * Returns the public key and offset for a computation definition account, given the circuit name and MXE program ID.
12366
+ * @param circuitName - The name of the circuit.
12367
+ * @param mxeProgramID - The public key of the MXE program.
12368
+ * @returns An object containing the public key and offset for the computation definition account.
12369
+ */
11844
12370
  function getCompDefAccInfo(circuitName, mxeProgramID) {
11845
12371
  const offset = getCompDefAccOffset(circuitName);
11846
12372
  const pda = getCompDefAccPDA(getArciumProgAddress(), mxeProgramID, offset);
11847
12373
  return { pubkey: pda, offset: Buffer.from(offset).readUInt32LE(0) };
11848
12374
  }
12375
+ /**
12376
+ * Returns the PDA for a computation definition account, given the program ID, MXE program ID, and offset.
12377
+ * @param arciumProgramID - The public key of the Arcium program.
12378
+ * @param mxeProgramID - The public key of the MXE program.
12379
+ * @param offset - The offset as a Uint8Array.
12380
+ * @returns The PDA for the computation definition account.
12381
+ */
11849
12382
  function getCompDefAccPDA(arciumProgramID, mxeProgramID, offset) {
11850
12383
  return anchor__namespace.web3.PublicKey.findProgramAddressSync([Buffer.from('ComputationDefinitionAccount', 'utf-8'), mxeProgramID.toBuffer(), offset], arciumProgramID)[0];
11851
12384
  }
11852
12385
 
11853
- // Reads local Arcium env information.
11854
- // Only available in Node.js and when testing locally.
12386
+ /**
12387
+ * Reads local Arcium environment information from environment variables.
12388
+ * Only available in Node.js and when testing locally.
12389
+ * @returns The local Arcium environment configuration.
12390
+ * @throws Error if called in a browser or if required environment variables are missing or invalid.
12391
+ */
11855
12392
  function getArciumEnv() {
11856
12393
  if (isBrowser()) {
11857
12394
  throw new Error('Arcium local env is not available in browser.');
@@ -12109,12 +12646,29 @@ class LogScanner {
12109
12646
  }
12110
12647
  }
12111
12648
 
12649
+ /**
12650
+ * Waits for the finalization of a computation by listening for the finalizeComputationEvent.
12651
+ * Resolves with the transaction signature once the computation is finalized.
12652
+ * @param provider - The Anchor provider to use for event listening.
12653
+ * @param computationOffset - The offset of the computation to wait for.
12654
+ * @param mxeProgramId - The public key of the MXE program.
12655
+ * @param commitment - (Optional) The desired finality/commitment level (default: 'confirmed').
12656
+ * @returns The transaction signature of the finalization event.
12657
+ */
12112
12658
  async function awaitComputationFinalization(provider, computationOffset, mxeProgramId, commitment = 'confirmed') {
12113
12659
  const arciumProgram = getArciumProgram(provider);
12114
12660
  const eventListener = new EventManager(arciumProgram.programId, provider, arciumProgram.coder);
12115
12661
  const finalizeComp = await awaitEvent(eventListener, 'finalizeComputationEvent', (e) => mxeProgramId.equals(e.mxeProgramId) && e.computationOffset.eq(computationOffset), commitment);
12116
12662
  return finalizeComp.sig;
12117
12663
  }
12664
+ /**
12665
+ * Waits for a specific event to occur, matching a custom check, and returns the event and its signature.
12666
+ * @param eventListener - The EventManager instance to use for listening.
12667
+ * @param eventName - The name of the event to listen for.
12668
+ * @param eventCheck - A predicate function to check if the event matches the desired criteria.
12669
+ * @param commitment - (Optional) The desired finality/commitment level (default: 'confirmed').
12670
+ * @returns An object containing the event and its transaction signature.
12671
+ */
12118
12672
  async function awaitEvent(eventListener, eventName, eventCheck, commitment = 'confirmed') {
12119
12673
  const foundEvent = await new Promise((res) => {
12120
12674
  const listenerId = eventListener.addEventListener(eventName, (event, _slot, signature) => {
@@ -12126,51 +12680,105 @@ async function awaitEvent(eventListener, eventName, eventCheck, commitment = 'co
12126
12680
  return { event: foundEvent[0], sig: foundEvent[1] };
12127
12681
  }
12128
12682
 
12683
+ /**
12684
+ * Returns the public key of the deployed Arcium program on Solana.
12685
+ * @returns The Arcium program's public key.
12686
+ */
12129
12687
  function getArciumProgramId() {
12130
12688
  return new web3_js.PublicKey('BKck65TgoKRokMjQM3datB9oRwJ8rAj2jxPXvHXUvcL6');
12131
12689
  }
12132
- function getComputationAcc(mxeProgramId, offset) {
12690
+ /**
12691
+ * Derives the computation account address for a given MXE program ID and offset.
12692
+ * @param mxeProgramId - The public key of the MXE program.
12693
+ * @param offset - The computation offset as an anchor.BN.
12694
+ * @returns The derived computation account public key.
12695
+ */
12696
+ function getComputationAccAddress(mxeProgramId, offset) {
12133
12697
  const seeds = [Buffer.from(COMPUTATION_ACC_SEED), mxeProgramId.toBuffer(), offset.toArrayLike(Buffer, 'le', 8)];
12134
12698
  return generateArciumPDAFrom(seeds)[0];
12135
12699
  }
12136
- function getMempoolAcc(mxeProgramId) {
12700
+ /**
12701
+ * Derives the mempool account address for a given MXE program ID.
12702
+ * @param mxeProgramId - The public key of the MXE program.
12703
+ * @returns The derived mempool account public key.
12704
+ */
12705
+ function getMempoolAccAddress(mxeProgramId) {
12137
12706
  const seeds = [Buffer.from(MEMPOOL_ACC_SEED), mxeProgramId.toBuffer()];
12138
12707
  return generateArciumPDAFrom(seeds)[0];
12139
12708
  }
12140
- function getExecutingPoolAcc(mxeProgramId) {
12709
+ /**
12710
+ * Derives the executing pool account address for a given MXE program ID.
12711
+ * @param mxeProgramId - The public key of the MXE program.
12712
+ * @returns The derived executing pool account public key.
12713
+ */
12714
+ function getExecutingPoolAccAddress(mxeProgramId) {
12141
12715
  const seeds = [Buffer.from(EXEC_POOL_ACC_SEED), mxeProgramId.toBuffer()];
12142
12716
  return generateArciumPDAFrom(seeds)[0];
12143
12717
  }
12144
- function getStakingPoolAcc() {
12718
+ /**
12719
+ * Derives the staking pool account address.
12720
+ * @returns The derived staking pool account public key.
12721
+ */
12722
+ function getStakingPoolAccAddress() {
12145
12723
  const seeds = [Buffer.from(POOL_ACC_SEED)];
12146
12724
  return generateArciumPDAFrom(seeds)[0];
12147
12725
  }
12148
- function getClockAcc() {
12726
+ /**
12727
+ * Derives the clock account address.
12728
+ * @returns The derived clock account public key.
12729
+ */
12730
+ function getClockAccAddress() {
12149
12731
  const seeds = [Buffer.from(CLOCK_ACC_SEED)];
12150
12732
  return generateArciumPDAFrom(seeds)[0];
12151
12733
  }
12152
- function getClusterAcc(offset) {
12734
+ /**
12735
+ * Derives the cluster account address for a given offset.
12736
+ * @param offset - The cluster offset as a number.
12737
+ * @returns The derived cluster account public key.
12738
+ */
12739
+ function getClusterAccAddress(offset) {
12153
12740
  const offsetBuffer = Buffer.alloc(4);
12154
12741
  offsetBuffer.writeUInt32LE(offset, 0);
12155
12742
  const seeds = [Buffer.from(CLUSTER_ACC_SEED), offsetBuffer];
12156
12743
  return generateArciumPDAFrom(seeds)[0];
12157
12744
  }
12158
- function getArxNodeAcc(offset) {
12745
+ /**
12746
+ * Derives the ArxNode account address for a given offset.
12747
+ * @param offset - The ArxNode offset as a number.
12748
+ * @returns The derived ArxNode account public key.
12749
+ */
12750
+ function getArxNodeAccAddress(offset) {
12159
12751
  const offsetBuffer = Buffer.alloc(4);
12160
12752
  offsetBuffer.writeUInt32LE(offset, 0);
12161
12753
  const seeds = [Buffer.from(ARX_NODE_ACC_SEED), offsetBuffer];
12162
12754
  return generateArciumPDAFrom(seeds)[0];
12163
12755
  }
12164
- function getMXEAccAcc(mxeProgramId) {
12756
+ /**
12757
+ * Derives the MXE account address for a given MXE program ID.
12758
+ * @param mxeProgramId - The public key of the MXE program.
12759
+ * @returns The derived MXE account public key.
12760
+ */
12761
+ function getMXEAccAddress(mxeProgramId) {
12165
12762
  const seeds = [Buffer.from(MXE_ACC_ACC_SEED), mxeProgramId.toBuffer()];
12166
12763
  return generateArciumPDAFrom(seeds)[0];
12167
12764
  }
12168
- function getCompDefAcc(mxeProgramId, offset) {
12765
+ /**
12766
+ * Derives the computation definition account address for a given MXE program ID and offset.
12767
+ * @param mxeProgramId - The public key of the MXE program.
12768
+ * @param offset - The computation definition offset as a number.
12769
+ * @returns The derived computation definition account public key.
12770
+ */
12771
+ function getCompDefAccAddress(mxeProgramId, offset) {
12169
12772
  const offsetBuffer = Buffer.alloc(4);
12170
12773
  offsetBuffer.writeUInt32LE(offset, 0);
12171
12774
  const seeds = [Buffer.from(COMP_DEF_ACC_SEED), mxeProgramId.toBuffer(), offsetBuffer];
12172
12775
  return generateArciumPDAFrom(seeds)[0];
12173
12776
  }
12777
+ /**
12778
+ * Generates a program-derived address (PDA) from the provided seeds and the Arcium program ID.
12779
+ * @param seeds - An array of Buffer seeds used for PDA derivation.
12780
+ * @returns A tuple containing the derived public key and the bump seed.
12781
+ */
12174
12782
  function generateArciumPDAFrom(seeds) {
12175
12783
  const programId = getArciumProgramId();
12176
12784
  return web3_js.PublicKey.findProgramAddressSync(seeds, programId);
@@ -12182,6 +12790,9 @@ Object.defineProperty(exports, "x25519", {
12182
12790
  });
12183
12791
  exports.ARCIUM_ADDR = ARCIUM_ADDR;
12184
12792
  exports.ARCIUM_IDL = ARCIUM_IDL;
12793
+ exports.Aes128Cipher = Aes128Cipher;
12794
+ exports.Aes192Cipher = Aes192Cipher;
12795
+ exports.Aes256Cipher = Aes256Cipher;
12185
12796
  exports.CURVE25519_BASE_FIELD = CURVE25519_BASE_FIELD;
12186
12797
  exports.CURVE25519_SCALAR_FIELD_MODULUS = CURVE25519_SCALAR_FIELD_MODULUS;
12187
12798
  exports.DOUBLE_PRECISION_MANTISSA = DOUBLE_PRECISION_MANTISSA;
@@ -12189,6 +12800,7 @@ exports.Matrix = Matrix;
12189
12800
  exports.RescueCipher = RescueCipher;
12190
12801
  exports.RescueDesc = RescueDesc;
12191
12802
  exports.RescuePrimeHash = RescuePrimeHash;
12803
+ exports.arcisEd25519 = arcisEd25519;
12192
12804
  exports.awaitComputationFinalization = awaitComputationFinalization;
12193
12805
  exports.buildFinalizeCompDefTx = buildFinalizeCompDefTx;
12194
12806
  exports.deserializeLE = deserializeLE;
@@ -12202,20 +12814,20 @@ exports.getArciumProgAddress = getArciumProgAddress;
12202
12814
  exports.getArciumProgram = getArciumProgram;
12203
12815
  exports.getArciumProgramId = getArciumProgramId;
12204
12816
  exports.getArciumProgramReadonly = getArciumProgramReadonly;
12205
- exports.getArxNodeAcc = getArxNodeAcc;
12206
- exports.getClockAcc = getClockAcc;
12207
- exports.getClusterAcc = getClusterAcc;
12817
+ exports.getArxNodeAccAddress = getArxNodeAccAddress;
12818
+ exports.getClockAccAddress = getClockAccAddress;
12819
+ exports.getClusterAccAddress = getClusterAccAddress;
12208
12820
  exports.getClusterDAInfo = getClusterDAInfo;
12209
- exports.getCompDefAcc = getCompDefAcc;
12821
+ exports.getCompDefAccAddress = getCompDefAccAddress;
12210
12822
  exports.getCompDefAccOffset = getCompDefAccOffset;
12211
- exports.getComputationAcc = getComputationAcc;
12823
+ exports.getComputationAccAddress = getComputationAccAddress;
12212
12824
  exports.getEncryptionKey = getEncryptionKey;
12213
- exports.getExecutingPoolAcc = getExecutingPoolAcc;
12825
+ exports.getExecutingPoolAccAddress = getExecutingPoolAccAddress;
12214
12826
  exports.getExecutingPoolAccData = getExecutingPoolAccData;
12215
- exports.getMXEAccAcc = getMXEAccAcc;
12216
- exports.getMempoolAcc = getMempoolAcc;
12827
+ exports.getMXEAccAddress = getMXEAccAddress;
12828
+ exports.getMempoolAccAddress = getMempoolAccAddress;
12217
12829
  exports.getMempoolAccData = getMempoolAccData;
12218
- exports.getStakingPoolAcc = getStakingPoolAcc;
12830
+ exports.getStakingPoolAccAddress = getStakingPoolAccAddress;
12219
12831
  exports.positiveModulo = positiveModulo;
12220
12832
  exports.randMatrix = randMatrix;
12221
12833
  exports.secretShareInputs = secretShareInputs;