@arcium-hq/client 0.9.2 → 0.9.4
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 +166 -11
- package/build/index.mjs +166 -12
- package/build/types/arcis/arcisModule.d.ts +26 -0
- package/build/types/arcis/arcisModule.d.ts.map +1 -0
- package/build/types/arcis/arcisType.d.ts +76 -0
- package/build/types/arcis/arcisType.d.ts.map +1 -0
- package/build/types/arcis/packer.d.ts +63 -0
- package/build/types/arcis/packer.d.ts.map +1 -0
- package/build/types/arcis/packing.d.ts +33 -0
- package/build/types/arcis/packing.d.ts.map +1 -0
- package/build/types/callback.d.ts +21 -0
- package/build/types/callback.d.ts.map +1 -0
- package/build/types/constants.d.ts +101 -0
- package/build/types/constants.d.ts.map +1 -0
- package/build/types/cryptography/aes128Cipher.d.ts +14 -0
- package/build/types/cryptography/aes128Cipher.d.ts.map +1 -0
- package/build/types/cryptography/aes192Cipher.d.ts +14 -0
- package/build/types/cryptography/aes192Cipher.d.ts.map +1 -0
- package/build/types/cryptography/aes256Cipher.d.ts +14 -0
- package/build/types/cryptography/aes256Cipher.d.ts.map +1 -0
- package/build/types/cryptography/aesCtrCipher.d.ts +36 -0
- package/build/types/cryptography/aesCtrCipher.d.ts.map +1 -0
- package/build/types/cryptography/arcisEd25519.d.ts +8 -0
- package/build/types/cryptography/arcisEd25519.d.ts.map +1 -0
- package/build/types/cryptography/cSplRescueCipher.d.ts +29 -0
- package/build/types/cryptography/cSplRescueCipher.d.ts.map +1 -0
- package/build/types/cryptography/cryptography.d.ts +38 -0
- package/build/types/cryptography/cryptography.d.ts.map +1 -0
- package/build/types/cryptography/hkdf.d.ts +37 -0
- package/build/types/cryptography/hkdf.d.ts.map +1 -0
- package/build/types/cryptography/hmac.d.ts +22 -0
- package/build/types/cryptography/hmac.d.ts.map +1 -0
- package/build/types/cryptography/rescueCipher.d.ts +29 -0
- package/build/types/cryptography/rescueCipher.d.ts.map +1 -0
- package/build/types/cryptography/rescueCipherCommon.d.ts +45 -0
- package/build/types/cryptography/rescueCipherCommon.d.ts.map +1 -0
- package/build/types/cryptography/rescueDesc.d.ts +80 -0
- package/build/types/cryptography/rescueDesc.d.ts.map +1 -0
- package/build/types/cryptography/rescuePrimeHash.d.ts +23 -0
- package/build/types/cryptography/rescuePrimeHash.d.ts.map +1 -0
- package/build/types/ctUtils.d.ts +50 -0
- package/build/types/ctUtils.d.ts.map +1 -0
- package/build/{index.d.ts → types/idl/arcium.d.ts} +156 -909
- package/build/types/idl/arcium.d.ts.map +1 -0
- package/build/types/idl/arcium_staking.d.ts +4589 -0
- package/build/types/idl/arcium_staking.d.ts.map +1 -0
- package/build/types/idl/index.d.ts +15 -0
- package/build/types/idl/index.d.ts.map +1 -0
- package/build/types/index.d.ts +33 -0
- package/build/types/index.d.ts.map +1 -0
- package/build/types/localEnv.d.ts +15 -0
- package/build/types/localEnv.d.ts.map +1 -0
- package/build/types/matrix.d.ts +39 -0
- package/build/types/matrix.d.ts.map +1 -0
- package/build/types/onchain.d.ts +223 -0
- package/build/types/onchain.d.ts.map +1 -0
- package/build/types/pda.d.ts +89 -0
- package/build/types/pda.d.ts.map +1 -0
- package/build/types/utils.d.ts +65 -0
- package/build/types/utils.d.ts.map +1 -0
- package/package.json +6 -6
- package/src/arcis/arcisModule.ts +39 -0
- package/src/arcis/arcisType.ts +303 -0
- package/src/arcis/packer.ts +152 -0
- package/src/arcis/packing.ts +115 -0
- package/src/callback.ts +101 -0
- package/src/constants.ts +104 -0
- package/src/cryptography/aes128Cipher.ts +16 -0
- package/src/cryptography/aes192Cipher.ts +16 -0
- package/src/cryptography/aes256Cipher.ts +16 -0
- package/src/cryptography/aesCtrCipher.ts +84 -0
- package/src/cryptography/arcisEd25519.ts +96 -0
- package/src/cryptography/cSplRescueCipher.ts +41 -0
- package/src/cryptography/cryptography.ts +82 -0
- package/src/cryptography/hkdf.ts +58 -0
- package/src/cryptography/hmac.ts +66 -0
- package/src/cryptography/rescueCipher.ts +41 -0
- package/src/cryptography/rescueCipherCommon.ts +211 -0
- package/src/cryptography/rescueDesc.ts +492 -0
- package/src/cryptography/rescuePrimeHash.ts +72 -0
- package/src/ctUtils.ts +124 -0
- package/src/idl/arcium.json +12424 -0
- package/src/idl/arcium.ts +12430 -0
- package/src/idl/arcium_staking.json +4582 -0
- package/src/idl/arcium_staking.ts +4588 -0
- package/src/idl/index.ts +20 -0
- package/src/index.ts +32 -0
- package/src/localEnv.ts +39 -0
- package/src/matrix.ts +215 -0
- package/src/onchain.ts +1020 -0
- package/src/pda.ts +203 -0
- package/src/utils.ts +126 -0
package/src/idl/index.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Arcium } from './arcium.js';
|
|
2
|
+
import * as ARCIUM_IDL_MODULE from './arcium.json' with { type: 'json' };
|
|
3
|
+
|
|
4
|
+
// Handle both ESM (ts-node wraps as {default: ...}) and bundled (direct) imports
|
|
5
|
+
const ARCIUM_IDL = ((ARCIUM_IDL_MODULE as { default?: Arcium }).default ?? ARCIUM_IDL_MODULE) as unknown as Arcium;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The deployed address of the Arcium program, as specified in the IDL.
|
|
9
|
+
*/
|
|
10
|
+
export const ARCIUM_ADDR = ARCIUM_IDL.address;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* The Anchor-generated IDL type for the Arcium program.
|
|
14
|
+
*/
|
|
15
|
+
export type { Arcium as ArciumIdlType };
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The Anchor-generated IDL JSON object for the Arcium program.
|
|
19
|
+
*/
|
|
20
|
+
export { ARCIUM_IDL };
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client SDK for encrypted Solana programs using Arcium MPC.
|
|
3
|
+
*
|
|
4
|
+
* Key exports:
|
|
5
|
+
* - {@link createPacker} - Pack/unpack circuit inputs and outputs
|
|
6
|
+
* - {@link awaitComputationFinalization} - Wait for computation results
|
|
7
|
+
* - Cryptography: AES, Rescue ciphers, HMAC, HKDF
|
|
8
|
+
* - PDAs: Address derivation utilities
|
|
9
|
+
*
|
|
10
|
+
* @packageDocumentation
|
|
11
|
+
*/
|
|
12
|
+
export * from './cryptography/cryptography.js';
|
|
13
|
+
export * from './cryptography/rescueCipher.js';
|
|
14
|
+
export * from './cryptography/cSplRescueCipher.js';
|
|
15
|
+
export * from './cryptography/rescuePrimeHash.js';
|
|
16
|
+
export * from './cryptography/rescueDesc.js';
|
|
17
|
+
export * from './cryptography/arcisEd25519.js';
|
|
18
|
+
export * from './cryptography/aes128Cipher.js';
|
|
19
|
+
export * from './cryptography/aes192Cipher.js';
|
|
20
|
+
export * from './cryptography/aes256Cipher.js';
|
|
21
|
+
export * from './arcis/arcisModule.js';
|
|
22
|
+
export * from './arcis/arcisType.js';
|
|
23
|
+
export { createPacker, type Packer } from './arcis/packer.js';
|
|
24
|
+
export * from './matrix.js';
|
|
25
|
+
export * from './onchain.js';
|
|
26
|
+
export type { MempoolPriorityFeeStats } from './onchain.js';
|
|
27
|
+
export * from './localEnv.js';
|
|
28
|
+
export * from './callback.js';
|
|
29
|
+
export * from './idl/index.js';
|
|
30
|
+
export * from './pda.js';
|
|
31
|
+
export { isNullRef, type ComputationReference } from './utils.js';
|
|
32
|
+
export { x25519 } from '@noble/curves/ed25519';
|
package/src/localEnv.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { isBrowser } from './utils.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Structure representing the local Arcium environment variables required for local development or testing.
|
|
5
|
+
*/
|
|
6
|
+
export type ArciumLocalEnv = {
|
|
7
|
+
arciumClusterOffset: number,
|
|
8
|
+
arciumBackupClusterOffset: number,
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Read local Arcium environment information from environment variables.
|
|
13
|
+
* Only available in Node.js and when testing locally.
|
|
14
|
+
* @returns Local Arcium environment configuration.
|
|
15
|
+
* @throws Error if called in a browser or if required environment variables are missing or invalid.
|
|
16
|
+
*/
|
|
17
|
+
export function getArciumEnv(): ArciumLocalEnv {
|
|
18
|
+
if (isBrowser()) {
|
|
19
|
+
throw new Error('Arcium local env is not available in browser.');
|
|
20
|
+
}
|
|
21
|
+
try {
|
|
22
|
+
const arciumClusterOffset = Number(process.env.ARCIUM_CLUSTER_OFFSET);
|
|
23
|
+
if (isNaN(arciumClusterOffset)) {
|
|
24
|
+
throw new Error('ARCIUM_CLUSTER_OFFSET environment variable is not set or is invalid (NaN).');
|
|
25
|
+
}
|
|
26
|
+
const arciumBackupClusterOffset = process.env.ARCIUM_BACKUP_CLUSTER_OFFSET;
|
|
27
|
+
const arciumBackupClusterOffsetNumber = Number(arciumBackupClusterOffset);
|
|
28
|
+
if (typeof arciumBackupClusterOffset !== 'undefined' && isNaN(arciumBackupClusterOffsetNumber)) {
|
|
29
|
+
throw new Error('ARCIUM_BACKUP_CLUSTER_OFFSET environment variable is invalid (NaN).');
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
arciumClusterOffset,
|
|
33
|
+
arciumBackupClusterOffset: arciumBackupClusterOffsetNumber,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
catch (e) {
|
|
37
|
+
throw new Error(`Encountered error while trying to parse env vars: ${e}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
package/src/matrix.ts
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { FpField } from './cryptography/rescueDesc.js';
|
|
2
|
+
import { generateRandomFieldElem } from './cryptography/cryptography.js';
|
|
3
|
+
import { getBinSize } from './utils.js';
|
|
4
|
+
import {
|
|
5
|
+
ctLt,
|
|
6
|
+
ctAdd,
|
|
7
|
+
ctSelect,
|
|
8
|
+
ctSub,
|
|
9
|
+
ctSignBit,
|
|
10
|
+
} from './ctUtils.js';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Matrix operations for MPC field arithmetic.
|
|
14
|
+
* Used internally by Rescue cipher. Not part of public API.
|
|
15
|
+
* @internal
|
|
16
|
+
*/
|
|
17
|
+
export class Matrix {
|
|
18
|
+
field: FpField;
|
|
19
|
+
|
|
20
|
+
data: readonly bigint[][];
|
|
21
|
+
|
|
22
|
+
constructor(field: FpField, data: readonly bigint[][]) {
|
|
23
|
+
this.field = field;
|
|
24
|
+
const nrows = data.length;
|
|
25
|
+
const ncols = data[0].length;
|
|
26
|
+
for (let i = 1; i < nrows; ++i) {
|
|
27
|
+
if (data[i].length !== ncols) {
|
|
28
|
+
throw Error('All rows must have same number of columns.');
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
this.data = data.map((row) => row.map((c) => field.create(c)));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Matrix multiplication between `this` and `rhs`.
|
|
36
|
+
*/
|
|
37
|
+
matMul(rhs: Matrix): Matrix {
|
|
38
|
+
const thisNrows = this.data.length;
|
|
39
|
+
const thisNcols = this.data[0].length;
|
|
40
|
+
const rhsNrows = rhs.data.length;
|
|
41
|
+
const rhsNcols = rhs.data[0].length;
|
|
42
|
+
if (thisNcols !== rhsNrows) {
|
|
43
|
+
throw Error(`this.ncols must be equal to rhs.nrows (found ${thisNcols} and ${rhsNrows})`);
|
|
44
|
+
}
|
|
45
|
+
const data = [];
|
|
46
|
+
for (let i = 0; i < thisNrows; ++i) {
|
|
47
|
+
const row = [];
|
|
48
|
+
for (let j = 0; j < rhsNcols; ++j) {
|
|
49
|
+
let c = this.field.ZERO;
|
|
50
|
+
for (let k = 0; k < thisNcols; ++k) {
|
|
51
|
+
c = this.field.add(c, this.field.mul(this.data[i][k], rhs.data[k][j]));
|
|
52
|
+
}
|
|
53
|
+
row.push(c);
|
|
54
|
+
}
|
|
55
|
+
data.push(row);
|
|
56
|
+
}
|
|
57
|
+
return new Matrix(this.field, data);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Element-wise addition between `this` and `rhs`.
|
|
62
|
+
*/
|
|
63
|
+
add(rhs: Matrix, ct: boolean = false): Matrix {
|
|
64
|
+
const thisNrows = this.data.length;
|
|
65
|
+
const thisNcols = this.data[0].length;
|
|
66
|
+
const rhsNrows = rhs.data.length;
|
|
67
|
+
const rhsNcols = rhs.data[0].length;
|
|
68
|
+
if (thisNrows !== rhsNrows) {
|
|
69
|
+
throw Error(`this.nrows must be equal to rhs.nrows (found ${thisNrows} and ${rhsNrows})`);
|
|
70
|
+
}
|
|
71
|
+
if (thisNcols !== rhsNcols) {
|
|
72
|
+
throw Error(`this.ncols must be equal to rhs.ncols (found ${thisNcols} and ${rhsNcols})`);
|
|
73
|
+
}
|
|
74
|
+
const binSize = getBinSize(this.field.ORDER - 1n);
|
|
75
|
+
const data = [];
|
|
76
|
+
for (let i = 0; i < thisNrows; ++i) {
|
|
77
|
+
const row = [];
|
|
78
|
+
for (let j = 0; j < thisNcols; ++j) {
|
|
79
|
+
if (ct) {
|
|
80
|
+
const sum = ctAdd(this.data[i][j], rhs.data[i][j], binSize);
|
|
81
|
+
row.push(ctSelect(ctLt(sum, this.field.ORDER, binSize), sum, ctSub(sum, this.field.ORDER, binSize), binSize));
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
row.push(this.field.add(this.data[i][j], rhs.data[i][j]));
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
data.push(row);
|
|
88
|
+
}
|
|
89
|
+
return new Matrix(this.field, data);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Element-wise subtraction between `this` and `rhs`.
|
|
94
|
+
*/
|
|
95
|
+
sub(rhs: Matrix, ct: boolean = false): Matrix {
|
|
96
|
+
const thisNrows = this.data.length;
|
|
97
|
+
const thisNcols = this.data[0].length;
|
|
98
|
+
const rhsNrows = rhs.data.length;
|
|
99
|
+
const rhsNcols = rhs.data[0].length;
|
|
100
|
+
if (thisNrows !== rhsNrows) {
|
|
101
|
+
throw Error(`this.nrows must be equal to rhs.nrows (found ${thisNrows} and ${rhsNrows})`);
|
|
102
|
+
}
|
|
103
|
+
if (thisNcols !== rhsNcols) {
|
|
104
|
+
throw Error(`this.ncols must be equal to rhs.ncols (found ${thisNcols} and ${rhsNcols})`);
|
|
105
|
+
}
|
|
106
|
+
const binSize = getBinSize(this.field.ORDER - 1n);
|
|
107
|
+
const data = [];
|
|
108
|
+
for (let i = 0; i < thisNrows; ++i) {
|
|
109
|
+
const row = [];
|
|
110
|
+
for (let j = 0; j < thisNcols; ++j) {
|
|
111
|
+
if (ct) {
|
|
112
|
+
const diff = ctSub(this.data[i][j], rhs.data[i][j], binSize);
|
|
113
|
+
row.push(ctSelect(ctSignBit(diff, binSize), ctAdd(diff, this.field.ORDER, binSize), diff, binSize));
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
row.push(this.field.sub(this.data[i][j], rhs.data[i][j]));
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
data.push(row);
|
|
120
|
+
}
|
|
121
|
+
return new Matrix(this.field, data);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Raises each element of `this` to the power `e`.
|
|
126
|
+
*/
|
|
127
|
+
pow(e: bigint): Matrix {
|
|
128
|
+
const data = [];
|
|
129
|
+
for (let i = 0; i < this.data.length; ++i) {
|
|
130
|
+
const row = [];
|
|
131
|
+
for (let j = 0; j < this.data[0].length; ++j) {
|
|
132
|
+
row.push(this.field.pow(this.data[i][j], e));
|
|
133
|
+
}
|
|
134
|
+
data.push(row);
|
|
135
|
+
}
|
|
136
|
+
return new Matrix(this.field, data);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Compute the determinant using Gauss elimination.
|
|
141
|
+
* Match the determinant implementation in Arcis.
|
|
142
|
+
*/
|
|
143
|
+
det(): bigint {
|
|
144
|
+
// Ensure the matrix is square
|
|
145
|
+
const n = this.data.length;
|
|
146
|
+
if (n === 0 || !this.is_square()) {
|
|
147
|
+
throw Error('Matrix must be square and non-empty to compute the determinant.');
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
let det = this.field.ONE;
|
|
151
|
+
// Clone the data to avoid mutating the original matrix
|
|
152
|
+
let rows = this.data.map((row) => [...row]);
|
|
153
|
+
|
|
154
|
+
for (let i = 0; i < n; ++i) {
|
|
155
|
+
// we partition into rows that have a leading zero and rows that don't
|
|
156
|
+
const lzRows = rows.filter((r) => this.field.is0(r[0]));
|
|
157
|
+
const nlzRows = rows.filter((r) => !this.field.is0(r[0]));
|
|
158
|
+
|
|
159
|
+
// take pivot element
|
|
160
|
+
const pivotRow = nlzRows.shift();
|
|
161
|
+
if (pivotRow === undefined) {
|
|
162
|
+
// no pivot row implies the rank is less than n i.e. the determinant is zero
|
|
163
|
+
return this.field.ZERO;
|
|
164
|
+
}
|
|
165
|
+
const pivot = pivotRow[0];
|
|
166
|
+
|
|
167
|
+
// multiply pivot onto the determinant
|
|
168
|
+
det = this.field.mul(det, pivot);
|
|
169
|
+
|
|
170
|
+
// subtract all leading non zero values with the pivot element (forward elimination).
|
|
171
|
+
|
|
172
|
+
const pivotInverse = this.field.inv(pivot);
|
|
173
|
+
// precomputing pivot row such that the leading value is one. This reduces the number of
|
|
174
|
+
// multiplications in the forward elimination multiplications by 50%
|
|
175
|
+
const normalizedPivotRow = pivotRow.map((v) => this.field.mul(pivotInverse, v));
|
|
176
|
+
|
|
177
|
+
// forward elimination with normalized pivot row
|
|
178
|
+
const nlzRowsProcessed = nlzRows.map((row) => {
|
|
179
|
+
const lead: bigint = row[0];
|
|
180
|
+
return row.map((value, index) => this.field.sub(value, this.field.mul(lead, normalizedPivotRow[index])));
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
// concat the reamining rows (without pivot row) and remove the pivot column (all first
|
|
184
|
+
// elements (i.e. zeros) from the remaining rows).
|
|
185
|
+
rows = nlzRowsProcessed.concat(lzRows).map((row) => row.slice(1));
|
|
186
|
+
}
|
|
187
|
+
return det;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
is_square(): boolean {
|
|
191
|
+
const n = this.data.length;
|
|
192
|
+
for (let i = 1; i < n; ++i) {
|
|
193
|
+
if (this.data[i].length !== n) {
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return true;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Generate random matrix for testing.
|
|
203
|
+
* @internal
|
|
204
|
+
*/
|
|
205
|
+
export function randMatrix(field: FpField, nrows: number, ncols: number): Matrix {
|
|
206
|
+
const data = [];
|
|
207
|
+
for (let i = 0; i < nrows; ++i) {
|
|
208
|
+
const row = [];
|
|
209
|
+
for (let j = 0; j < ncols; ++j) {
|
|
210
|
+
row.push(generateRandomFieldElem(field.ORDER));
|
|
211
|
+
}
|
|
212
|
+
data.push(row);
|
|
213
|
+
}
|
|
214
|
+
return new Matrix(field, data);
|
|
215
|
+
}
|