@arcium-hq/client 0.6.0 → 0.6.1
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 +215 -52
- package/build/index.d.ts +41 -7
- package/build/index.mjs +213 -53
- package/package.json +1 -1
package/build/index.cjs
CHANGED
|
@@ -281,6 +281,28 @@ function encodeAsRescueEncryptable(v) {
|
|
|
281
281
|
}
|
|
282
282
|
throw new Error('Invalid type to convert from number to bigint');
|
|
283
283
|
}
|
|
284
|
+
/**
|
|
285
|
+
* Decodes a Rescue-decrypted value back to a signed bigint.
|
|
286
|
+
* Handles the conversion from field element representation to signed integer.
|
|
287
|
+
* @param v - The decrypted field element value
|
|
288
|
+
* @returns The decoded signed bigint value
|
|
289
|
+
*/
|
|
290
|
+
function decodeRescueDecryptedToBigInt(v) {
|
|
291
|
+
const twoInv = (CURVE25519_BASE_FIELD.ORDER + 1n) / 2n;
|
|
292
|
+
const binSize = getBinSize(CURVE25519_BASE_FIELD.ORDER - 1n);
|
|
293
|
+
const isLtTwoInv = ctLt(v, twoInv, binSize);
|
|
294
|
+
return ctSelect(isLtTwoInv, v, ctSub(v, CURVE25519_BASE_FIELD.ORDER, binSize), binSize);
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Decodes a Rescue-decrypted value back to a JavaScript number.
|
|
298
|
+
* Converts from field element representation to a floating-point number.
|
|
299
|
+
* @param v - The decrypted field element value
|
|
300
|
+
* @returns The decoded number value
|
|
301
|
+
*/
|
|
302
|
+
function decodeRescueDecryptedToNumber(v) {
|
|
303
|
+
const vSigned = decodeRescueDecryptedToBigInt(v);
|
|
304
|
+
return Number(vSigned) * 2 ** -DOUBLE_PRECISION_MANTISSA;
|
|
305
|
+
}
|
|
284
306
|
/**
|
|
285
307
|
* Checks if a computation reference is null (all zeros).
|
|
286
308
|
* @param ref - The computation reference to check
|
|
@@ -1271,22 +1293,22 @@ class Aes256Cipher extends AesCtrCipher {
|
|
|
1271
1293
|
}
|
|
1272
1294
|
|
|
1273
1295
|
class DataSize {
|
|
1274
|
-
|
|
1296
|
+
isFull;
|
|
1275
1297
|
size;
|
|
1276
1298
|
index;
|
|
1277
1299
|
constructor(index, size) {
|
|
1278
|
-
const
|
|
1279
|
-
this.
|
|
1280
|
-
this.size =
|
|
1300
|
+
const isUndefined = size === undefined;
|
|
1301
|
+
this.isFull = isUndefined;
|
|
1302
|
+
this.size = isUndefined ? 0 : size;
|
|
1281
1303
|
this.index = index;
|
|
1282
1304
|
}
|
|
1283
1305
|
}
|
|
1284
1306
|
function sortDataSizes(arr) {
|
|
1285
|
-
arr.sort((left, right) => {
|
|
1286
|
-
if (left.
|
|
1287
|
-
return left.
|
|
1307
|
+
return [...arr].sort((left, right) => {
|
|
1308
|
+
if (left.isFull !== right.isFull) {
|
|
1309
|
+
return left.isFull ? -1 : 1;
|
|
1288
1310
|
}
|
|
1289
|
-
if (left.size
|
|
1311
|
+
if (left.size !== right.size) {
|
|
1290
1312
|
return right.size - left.size;
|
|
1291
1313
|
}
|
|
1292
1314
|
return left.index - right.index;
|
|
@@ -1309,7 +1331,7 @@ class PackingState {
|
|
|
1309
1331
|
this.maxSize = maxSize;
|
|
1310
1332
|
}
|
|
1311
1333
|
getCurrentLoad(index) {
|
|
1312
|
-
return this.loads[index]
|
|
1334
|
+
return this.loads[index] === undefined ? 0 : this.loads[index];
|
|
1313
1335
|
}
|
|
1314
1336
|
canFit(index, size) {
|
|
1315
1337
|
return this.getCurrentLoad(index) + size <= this.maxSize;
|
|
@@ -1324,7 +1346,7 @@ class PackingState {
|
|
|
1324
1346
|
return this.lastInsert + 1;
|
|
1325
1347
|
}
|
|
1326
1348
|
insert(size) {
|
|
1327
|
-
if (size.
|
|
1349
|
+
if (size.isFull) {
|
|
1328
1350
|
this.lastInsert = this.nFull;
|
|
1329
1351
|
this.nFull++;
|
|
1330
1352
|
return new PackLocation(this.lastInsert, 0);
|
|
@@ -1339,23 +1361,27 @@ class PackingState {
|
|
|
1339
1361
|
}
|
|
1340
1362
|
}
|
|
1341
1363
|
function packing(maxSize, arr) {
|
|
1342
|
-
sortDataSizes(arr);
|
|
1364
|
+
const sortedArr = sortDataSizes(arr);
|
|
1343
1365
|
const inserts = [];
|
|
1344
1366
|
const state = new PackingState(maxSize);
|
|
1345
|
-
|
|
1367
|
+
sortedArr.forEach((value) => {
|
|
1346
1368
|
const pack = state.insert(value);
|
|
1347
1369
|
inserts.push([value.index, pack]);
|
|
1348
1370
|
});
|
|
1349
|
-
const
|
|
1371
|
+
const nPacks = state.nFull + state.loads.length;
|
|
1350
1372
|
inserts.sort((left, right) => left[0] - right[0]);
|
|
1351
1373
|
const res = inserts.map((arg) => arg[1]);
|
|
1352
|
-
return [
|
|
1374
|
+
return [nPacks, res];
|
|
1353
1375
|
}
|
|
1354
1376
|
const ARCIS_PACKING_SIZE = 214;
|
|
1355
1377
|
function arcisPacking(arr) {
|
|
1356
1378
|
return packing(ARCIS_PACKING_SIZE, arr);
|
|
1357
1379
|
}
|
|
1358
1380
|
|
|
1381
|
+
/** Length of a Pubkey in bytes (Solana public keys are 32 bytes) */
|
|
1382
|
+
const PUBKEY_BYTE_LENGTH = 32;
|
|
1383
|
+
/** Maximum value a Pubkey bigint can hold (2^256) */
|
|
1384
|
+
const PUBKEY_MAX_VALUE = 1n << 256n;
|
|
1359
1385
|
var ArcisValueKind;
|
|
1360
1386
|
(function (ArcisValueKind) {
|
|
1361
1387
|
ArcisValueKind[ArcisValueKind["Integer"] = 0] = "Integer";
|
|
@@ -1377,10 +1403,10 @@ class IntegerInfo {
|
|
|
1377
1403
|
minValue() {
|
|
1378
1404
|
return this.signed ? -1n << (this.width - 1n) : 0n;
|
|
1379
1405
|
}
|
|
1380
|
-
|
|
1381
|
-
const
|
|
1382
|
-
const
|
|
1383
|
-
return
|
|
1406
|
+
isWithinBounds(b) {
|
|
1407
|
+
const minVal = this.minValue();
|
|
1408
|
+
const maxVal = this.signed ? 1n << (this.width - 1n) : 1n << this.width;
|
|
1409
|
+
return minVal <= b && b < maxVal;
|
|
1384
1410
|
}
|
|
1385
1411
|
name() {
|
|
1386
1412
|
return (this.signed ? "i" : "u") + this.width;
|
|
@@ -1414,9 +1440,9 @@ class ArcisValueField {
|
|
|
1414
1440
|
kind = ArcisValueKind.Pubkey;
|
|
1415
1441
|
break;
|
|
1416
1442
|
}
|
|
1417
|
-
if (kind
|
|
1418
|
-
if (typeof rawType
|
|
1419
|
-
throw TypeError("
|
|
1443
|
+
if (kind === ArcisValueKind.Integer) {
|
|
1444
|
+
if (typeof rawType === "string") {
|
|
1445
|
+
throw new TypeError("Expected Integer type object with signed/width properties");
|
|
1420
1446
|
}
|
|
1421
1447
|
const info = IntegerInfo.fromJson(rawType.Integer);
|
|
1422
1448
|
return new ArcisValueField(name, kind, info);
|
|
@@ -1426,38 +1452,63 @@ class ArcisValueField {
|
|
|
1426
1452
|
}
|
|
1427
1453
|
}
|
|
1428
1454
|
toBigInt(arg) {
|
|
1455
|
+
if (this.kind === ArcisValueKind.Float) {
|
|
1456
|
+
if (typeof arg !== 'number') {
|
|
1457
|
+
throw new TypeError(`Field ${this.name} expected a number, got ${typeof arg}`);
|
|
1458
|
+
}
|
|
1459
|
+
return encodeAsRescueEncryptable(arg);
|
|
1460
|
+
}
|
|
1461
|
+
let value = arg;
|
|
1462
|
+
if (typeof value === 'number') {
|
|
1463
|
+
if (!Number.isInteger(value)) {
|
|
1464
|
+
throw new TypeError(`Field ${this.name}: expected integer, got float ${value}`);
|
|
1465
|
+
}
|
|
1466
|
+
if (!Number.isSafeInteger(value)) {
|
|
1467
|
+
throw new RangeError(`Field ${this.name}: ${value} exceeds safe integer range, use BigInt`);
|
|
1468
|
+
}
|
|
1469
|
+
value = BigInt(value);
|
|
1470
|
+
}
|
|
1429
1471
|
switch (this.kind) {
|
|
1430
1472
|
case ArcisValueKind.Bool:
|
|
1431
|
-
if (typeof
|
|
1432
|
-
throw new TypeError(
|
|
1473
|
+
if (typeof value !== 'boolean') {
|
|
1474
|
+
throw new TypeError(`Field ${this.name} expected a boolean, got ${typeof value}`);
|
|
1433
1475
|
}
|
|
1434
|
-
return BigInt(
|
|
1435
|
-
case ArcisValueKind.Float:
|
|
1436
|
-
if (typeof arg != "number") {
|
|
1437
|
-
throw new TypeError("Field " + this.name + " expected a `number`, got `" + typeof arg + "`.");
|
|
1438
|
-
}
|
|
1439
|
-
return encodeAsRescueEncryptable(arg);
|
|
1476
|
+
return BigInt(value);
|
|
1440
1477
|
case ArcisValueKind.FullInteger:
|
|
1441
|
-
if (typeof
|
|
1442
|
-
throw new TypeError(
|
|
1478
|
+
if (typeof value !== 'bigint') {
|
|
1479
|
+
throw new TypeError(`Field ${this.name} expected a bigint, got ${typeof value}`);
|
|
1443
1480
|
}
|
|
1444
|
-
return
|
|
1481
|
+
return value;
|
|
1445
1482
|
case ArcisValueKind.Integer:
|
|
1446
|
-
if (typeof
|
|
1447
|
-
throw new TypeError(
|
|
1483
|
+
if (typeof value !== 'bigint') {
|
|
1484
|
+
throw new TypeError(`Field ${this.name} expected a bigint, got ${typeof value}`);
|
|
1448
1485
|
}
|
|
1449
|
-
if (
|
|
1450
|
-
throw new TypeError(
|
|
1486
|
+
if (this.info === undefined) {
|
|
1487
|
+
throw new TypeError(`Field ${this.name} is an integer, but signedness and width are unknown`);
|
|
1451
1488
|
}
|
|
1452
|
-
if (!this.info.
|
|
1453
|
-
|
|
1489
|
+
if (!this.info.isWithinBounds(value)) {
|
|
1490
|
+
const min = this.info.minValue();
|
|
1491
|
+
const max = this.info.signed ? (1n << (this.info.width - 1n)) - 1n : (1n << this.info.width) - 1n;
|
|
1492
|
+
throw new RangeError(`Field "${this.name}" (${this.info.name()}): value ${value} out of range [${min}, ${max}]`);
|
|
1454
1493
|
}
|
|
1455
|
-
return
|
|
1456
|
-
case ArcisValueKind.Pubkey:
|
|
1457
|
-
if (!(
|
|
1458
|
-
throw new TypeError(
|
|
1494
|
+
return value - this.info.minValue();
|
|
1495
|
+
case ArcisValueKind.Pubkey: {
|
|
1496
|
+
if (!(value instanceof Uint8Array)) {
|
|
1497
|
+
throw new TypeError(`Field ${this.name} expected a Uint8Array, got ${typeof value}`);
|
|
1459
1498
|
}
|
|
1460
|
-
|
|
1499
|
+
if (value.length !== PUBKEY_BYTE_LENGTH) {
|
|
1500
|
+
throw new RangeError(`Field ${this.name} expected ${PUBKEY_BYTE_LENGTH}-byte Uint8Array, got ${value.length} bytes`);
|
|
1501
|
+
}
|
|
1502
|
+
let pubkeyResult = 0n;
|
|
1503
|
+
for (let i = 0; i < PUBKEY_BYTE_LENGTH; i++) {
|
|
1504
|
+
pubkeyResult |= BigInt(value[i]) << BigInt(i * 8);
|
|
1505
|
+
}
|
|
1506
|
+
return pubkeyResult;
|
|
1507
|
+
}
|
|
1508
|
+
default: {
|
|
1509
|
+
const _exhaustive = this.kind;
|
|
1510
|
+
throw new Error(`Unhandled ArcisValueKind: ${_exhaustive}`);
|
|
1511
|
+
}
|
|
1461
1512
|
}
|
|
1462
1513
|
}
|
|
1463
1514
|
fromBigInt(arg) {
|
|
@@ -1469,21 +1520,58 @@ class ArcisValueField {
|
|
|
1469
1520
|
case 1n:
|
|
1470
1521
|
return true;
|
|
1471
1522
|
default:
|
|
1472
|
-
throw new
|
|
1523
|
+
throw new RangeError(`Field ${this.name}: Bool must be 0 or 1, got ${arg}`);
|
|
1473
1524
|
}
|
|
1474
1525
|
case ArcisValueKind.Float:
|
|
1475
|
-
return
|
|
1526
|
+
return decodeRescueDecryptedToNumber(arg);
|
|
1476
1527
|
case ArcisValueKind.FullInteger:
|
|
1477
1528
|
return arg;
|
|
1478
1529
|
case ArcisValueKind.Integer:
|
|
1479
|
-
if (this.info
|
|
1480
|
-
throw TypeError("Integer type without integer info");
|
|
1530
|
+
if (this.info === undefined) {
|
|
1531
|
+
throw new TypeError("Integer type without integer info");
|
|
1481
1532
|
}
|
|
1482
1533
|
return arg + this.info.minValue();
|
|
1483
|
-
case ArcisValueKind.Pubkey:
|
|
1484
|
-
|
|
1534
|
+
case ArcisValueKind.Pubkey: {
|
|
1535
|
+
if (arg < 0n) {
|
|
1536
|
+
throw new RangeError(`Field ${this.name}: Pubkey cannot be negative`);
|
|
1537
|
+
}
|
|
1538
|
+
if (arg >= PUBKEY_MAX_VALUE) {
|
|
1539
|
+
throw new RangeError(`Field ${this.name}: Pubkey exceeds 256 bits`);
|
|
1540
|
+
}
|
|
1541
|
+
const pubkeyBytes = new Uint8Array(PUBKEY_BYTE_LENGTH);
|
|
1542
|
+
let remaining = arg;
|
|
1543
|
+
for (let i = 0; i < PUBKEY_BYTE_LENGTH; i++) {
|
|
1544
|
+
pubkeyBytes[i] = Number(remaining & 0xffn);
|
|
1545
|
+
remaining >>= 8n;
|
|
1546
|
+
}
|
|
1547
|
+
return pubkeyBytes;
|
|
1548
|
+
}
|
|
1549
|
+
default: {
|
|
1550
|
+
const _exhaustive = this.kind;
|
|
1551
|
+
throw new Error(`Unhandled ArcisValueKind: ${_exhaustive}`);
|
|
1552
|
+
}
|
|
1485
1553
|
}
|
|
1486
1554
|
}
|
|
1555
|
+
static fromFieldInfo(info) {
|
|
1556
|
+
const name = info.name;
|
|
1557
|
+
if (info.type === 'Bool') {
|
|
1558
|
+
return new ArcisValueField(name, ArcisValueKind.Bool);
|
|
1559
|
+
}
|
|
1560
|
+
if (info.type === 'FullInteger') {
|
|
1561
|
+
return new ArcisValueField(name, ArcisValueKind.FullInteger);
|
|
1562
|
+
}
|
|
1563
|
+
if (info.type === 'Float') {
|
|
1564
|
+
return new ArcisValueField(name, ArcisValueKind.Float);
|
|
1565
|
+
}
|
|
1566
|
+
if (info.type === 'Pubkey') {
|
|
1567
|
+
return new ArcisValueField(name, ArcisValueKind.Pubkey);
|
|
1568
|
+
}
|
|
1569
|
+
if (typeof info.type === 'object' && 'Integer' in info.type) {
|
|
1570
|
+
const intInfo = new IntegerInfo(info.type.Integer.signed, BigInt(info.type.Integer.width));
|
|
1571
|
+
return new ArcisValueField(name, ArcisValueKind.Integer, intInfo);
|
|
1572
|
+
}
|
|
1573
|
+
throw new TypeError(`Unknown field type for ${name}`);
|
|
1574
|
+
}
|
|
1487
1575
|
toDataSize(index) {
|
|
1488
1576
|
switch (this.kind) {
|
|
1489
1577
|
case ArcisValueKind.Pubkey:
|
|
@@ -1507,6 +1595,9 @@ class ArcisType {
|
|
|
1507
1595
|
this.fields = fields;
|
|
1508
1596
|
}
|
|
1509
1597
|
pack(rawData) {
|
|
1598
|
+
if (rawData.length !== this.fields.length) {
|
|
1599
|
+
throw new RangeError(`Expected ${this.fields.length} fields, got ${rawData.length}`);
|
|
1600
|
+
}
|
|
1510
1601
|
const data = rawData.map((val, index) => this.fields[index].toBigInt(val));
|
|
1511
1602
|
const dataSizes = this.fields.map((field, index) => field.toDataSize(index));
|
|
1512
1603
|
const packing = arcisPacking(dataSizes);
|
|
@@ -1521,11 +1612,14 @@ class ArcisType {
|
|
|
1521
1612
|
unpack(packed) {
|
|
1522
1613
|
const dataSizes = this.fields.map((field, index) => field.toDataSize(index));
|
|
1523
1614
|
const packing = arcisPacking(dataSizes);
|
|
1615
|
+
if (packed.length < packing[0]) {
|
|
1616
|
+
throw new RangeError(`Expected at least ${packing[0]} packed elements, got ${packed.length}`);
|
|
1617
|
+
}
|
|
1524
1618
|
const res = [];
|
|
1525
1619
|
for (let idx = 0; idx < dataSizes.length; idx++) {
|
|
1526
1620
|
const packLocation = packing[1][idx];
|
|
1527
1621
|
const dataSize = dataSizes[idx];
|
|
1528
|
-
const val = dataSize.
|
|
1622
|
+
const val = dataSize.isFull ? packed[packLocation.index] : (packed[packLocation.index] >> BigInt(packLocation.offset)) % (1n << BigInt(dataSize.size));
|
|
1529
1623
|
res.push(this.fields[idx].fromBigInt(val));
|
|
1530
1624
|
}
|
|
1531
1625
|
return res;
|
|
@@ -1557,10 +1651,76 @@ class ArcisModule {
|
|
|
1557
1651
|
}
|
|
1558
1652
|
}
|
|
1559
1653
|
|
|
1560
|
-
|
|
1654
|
+
function parseFieldName(name) {
|
|
1655
|
+
const match = name.match(/^(.+)\[(\d+)\]$/);
|
|
1656
|
+
if (match) {
|
|
1657
|
+
return { base: match[1], index: parseInt(match[2], 10) };
|
|
1658
|
+
}
|
|
1659
|
+
return { base: name, index: null };
|
|
1660
|
+
}
|
|
1661
|
+
function extractValue(data, fieldName) {
|
|
1662
|
+
const { base, index } = parseFieldName(fieldName);
|
|
1663
|
+
const value = data[base];
|
|
1664
|
+
if (index !== null) {
|
|
1665
|
+
if (!Array.isArray(value)) {
|
|
1666
|
+
throw new TypeError(`Field "${base}" should be an array`);
|
|
1667
|
+
}
|
|
1668
|
+
if (index >= value.length) {
|
|
1669
|
+
throw new RangeError(`Field "${base}[${index}]" out of bounds (array length: ${value.length})`);
|
|
1670
|
+
}
|
|
1671
|
+
return value[index];
|
|
1672
|
+
}
|
|
1673
|
+
return value;
|
|
1674
|
+
}
|
|
1675
|
+
function groupUnpackedValues(values, fieldNames) {
|
|
1676
|
+
const result = {};
|
|
1677
|
+
for (let i = 0; i < fieldNames.length; i++) {
|
|
1678
|
+
const { base, index } = parseFieldName(fieldNames[i]);
|
|
1679
|
+
const value = values[i];
|
|
1680
|
+
if (index !== null) {
|
|
1681
|
+
if (!result[base]) {
|
|
1682
|
+
result[base] = [];
|
|
1683
|
+
}
|
|
1684
|
+
result[base][index] = value;
|
|
1685
|
+
}
|
|
1686
|
+
else {
|
|
1687
|
+
result[base] = value;
|
|
1688
|
+
}
|
|
1689
|
+
}
|
|
1690
|
+
return result;
|
|
1691
|
+
}
|
|
1692
|
+
/**
|
|
1693
|
+
* Creates a type-safe packer from field definitions.
|
|
1694
|
+
* Use `as const` on the fields array for compile-time field name validation.
|
|
1695
|
+
* @param fields - Field definitions from generated code.
|
|
1696
|
+
* @param typeName - Type name for debugging.
|
|
1697
|
+
*/
|
|
1698
|
+
function createPacker(fields, typeName = 'Packer') {
|
|
1699
|
+
const arcisFields = fields.map(f => ArcisValueField.fromFieldInfo(f));
|
|
1700
|
+
const arcisType = new ArcisType(typeName, arcisFields);
|
|
1701
|
+
const fieldNames = fields.map(f => f.name);
|
|
1702
|
+
return {
|
|
1703
|
+
pack(data) {
|
|
1704
|
+
const arr = fieldNames.map(name => {
|
|
1705
|
+
const value = extractValue(data, name);
|
|
1706
|
+
if (value === undefined) {
|
|
1707
|
+
throw new Error(`Missing required field: "${name}"`);
|
|
1708
|
+
}
|
|
1709
|
+
return value;
|
|
1710
|
+
});
|
|
1711
|
+
return arcisType.pack(arr);
|
|
1712
|
+
},
|
|
1713
|
+
unpack(packed) {
|
|
1714
|
+
const arr = arcisType.unpack(packed);
|
|
1715
|
+
return groupUnpackedValues(arr, fieldNames);
|
|
1716
|
+
}
|
|
1717
|
+
};
|
|
1718
|
+
}
|
|
1719
|
+
|
|
1720
|
+
var address = "Arcj82pX7HxYKLR92qvgZUAd7vGS1k4hQvAFcPATFdEQ";
|
|
1561
1721
|
var metadata = {
|
|
1562
1722
|
name: "arcium",
|
|
1563
|
-
version: "0.6.
|
|
1723
|
+
version: "0.6.1",
|
|
1564
1724
|
spec: "0.1.0",
|
|
1565
1725
|
description: "The Arcium program"
|
|
1566
1726
|
};
|
|
@@ -13452,8 +13612,10 @@ exports.Aes192Cipher = Aes192Cipher;
|
|
|
13452
13612
|
exports.Aes256Cipher = Aes256Cipher;
|
|
13453
13613
|
exports.ArcisModule = ArcisModule;
|
|
13454
13614
|
exports.ArcisType = ArcisType;
|
|
13615
|
+
exports.ArcisValueField = ArcisValueField;
|
|
13455
13616
|
exports.CURVE25519_BASE_FIELD = CURVE25519_BASE_FIELD;
|
|
13456
13617
|
exports.CURVE25519_SCALAR_FIELD_MODULUS = CURVE25519_SCALAR_FIELD_MODULUS;
|
|
13618
|
+
exports.IntegerInfo = IntegerInfo;
|
|
13457
13619
|
exports.Matrix = Matrix;
|
|
13458
13620
|
exports.RescueCipher = RescueCipher;
|
|
13459
13621
|
exports.RescueDesc = RescueDesc;
|
|
@@ -13461,6 +13623,7 @@ exports.RescuePrimeHash = RescuePrimeHash;
|
|
|
13461
13623
|
exports.arcisEd25519 = arcisEd25519;
|
|
13462
13624
|
exports.awaitComputationFinalization = awaitComputationFinalization;
|
|
13463
13625
|
exports.buildFinalizeCompDefTx = buildFinalizeCompDefTx;
|
|
13626
|
+
exports.createPacker = createPacker;
|
|
13464
13627
|
exports.deserializeLE = deserializeLE;
|
|
13465
13628
|
exports.finalizeKeyRecoveryExecution = finalizeKeyRecoveryExecution;
|
|
13466
13629
|
exports.generateRandomFieldElem = generateRandomFieldElem;
|
package/build/index.d.ts
CHANGED
|
@@ -297,12 +297,21 @@ declare class Aes256Cipher extends AesCtrCipher {
|
|
|
297
297
|
}
|
|
298
298
|
|
|
299
299
|
declare class DataSize {
|
|
300
|
-
|
|
300
|
+
isFull: boolean;
|
|
301
301
|
size: number;
|
|
302
302
|
index: number;
|
|
303
303
|
constructor(index: number, size?: number);
|
|
304
304
|
}
|
|
305
305
|
|
|
306
|
+
interface FieldInfo {
|
|
307
|
+
name: string;
|
|
308
|
+
type: {
|
|
309
|
+
Integer: {
|
|
310
|
+
signed: boolean;
|
|
311
|
+
width: number;
|
|
312
|
+
};
|
|
313
|
+
} | 'Bool' | 'FullInteger' | 'Float' | 'Pubkey';
|
|
314
|
+
}
|
|
306
315
|
declare enum ArcisValueKind {
|
|
307
316
|
Integer = 0,
|
|
308
317
|
FullInteger = 1,
|
|
@@ -319,7 +328,7 @@ declare class IntegerInfo {
|
|
|
319
328
|
"width": number;
|
|
320
329
|
}): IntegerInfo;
|
|
321
330
|
minValue(): bigint;
|
|
322
|
-
|
|
331
|
+
isWithinBounds(b: bigint): boolean;
|
|
323
332
|
name(): string;
|
|
324
333
|
}
|
|
325
334
|
declare class ArcisValueField {
|
|
@@ -330,6 +339,7 @@ declare class ArcisValueField {
|
|
|
330
339
|
static fromJson(json: unknown): ArcisValueField;
|
|
331
340
|
toBigInt(arg: unknown): bigint;
|
|
332
341
|
fromBigInt(arg: bigint): boolean | number | bigint | Uint8Array;
|
|
342
|
+
static fromFieldInfo(info: FieldInfo): ArcisValueField;
|
|
333
343
|
toDataSize(index: number): DataSize;
|
|
334
344
|
}
|
|
335
345
|
declare class ArcisType {
|
|
@@ -352,6 +362,30 @@ declare class ArcisModule {
|
|
|
352
362
|
static loadFromFile(path: string): ArcisModule;
|
|
353
363
|
}
|
|
354
364
|
|
|
365
|
+
/**
|
|
366
|
+
* Type-safe packer interface for generated code.
|
|
367
|
+
*/
|
|
368
|
+
interface Packer<TInput, TOutput> {
|
|
369
|
+
pack(data: TInput): bigint[];
|
|
370
|
+
unpack(packed: bigint[]): TOutput;
|
|
371
|
+
}
|
|
372
|
+
/** Extracts base field name from array-indexed names: "bytes[0]" -> "bytes" */
|
|
373
|
+
type ExtractBaseName<T extends string> = T extends `${infer Base}[${string}]` ? Base : T;
|
|
374
|
+
/** Extracts all base field names from a readonly FieldInfo array. */
|
|
375
|
+
type FieldBaseNames<T extends readonly FieldInfo[]> = ExtractBaseName<T[number]['name']>;
|
|
376
|
+
/**
|
|
377
|
+
* Validates that field base names match TInput keys. Returns `never` on mismatch.
|
|
378
|
+
* Only validates when using `as const`; skipped if types widen to `string`.
|
|
379
|
+
*/
|
|
380
|
+
type ValidateFieldNames<TInput, TFields extends readonly FieldInfo[]> = string extends FieldBaseNames<TFields> ? TFields : FieldBaseNames<TFields> extends keyof TInput ? TFields : never;
|
|
381
|
+
/**
|
|
382
|
+
* Creates a type-safe packer from field definitions.
|
|
383
|
+
* Use `as const` on the fields array for compile-time field name validation.
|
|
384
|
+
* @param fields - Field definitions from generated code.
|
|
385
|
+
* @param typeName - Type name for debugging.
|
|
386
|
+
*/
|
|
387
|
+
declare function createPacker<TInput extends Record<string, unknown>, TOutput extends Record<string, unknown>, const TFields extends readonly FieldInfo[] = readonly FieldInfo[]>(fields: TFields & ValidateFieldNames<TInput, TFields>, typeName?: string): Packer<TInput, TOutput>;
|
|
388
|
+
|
|
355
389
|
/**
|
|
356
390
|
* Program IDL in camelCase format in order to be used in JS/TS.
|
|
357
391
|
*
|
|
@@ -359,10 +393,10 @@ declare class ArcisModule {
|
|
|
359
393
|
* IDL can be found at `target/idl/arcium.json`.
|
|
360
394
|
*/
|
|
361
395
|
type Arcium = {
|
|
362
|
-
"address": "
|
|
396
|
+
"address": "Arcj82pX7HxYKLR92qvgZUAd7vGS1k4hQvAFcPATFdEQ";
|
|
363
397
|
"metadata": {
|
|
364
398
|
"name": "arcium";
|
|
365
|
-
"version": "0.6.
|
|
399
|
+
"version": "0.6.1";
|
|
366
400
|
"spec": "0.1.0";
|
|
367
401
|
"description": "The Arcium program";
|
|
368
402
|
};
|
|
@@ -11337,7 +11371,7 @@ declare const ARCIUM_IDL: Arcium;
|
|
|
11337
11371
|
/**
|
|
11338
11372
|
* The deployed address of the Arcium program, as specified in the IDL.
|
|
11339
11373
|
*/
|
|
11340
|
-
declare const ARCIUM_ADDR: "
|
|
11374
|
+
declare const ARCIUM_ADDR: "Arcj82pX7HxYKLR92qvgZUAd7vGS1k4hQvAFcPATFdEQ";
|
|
11341
11375
|
|
|
11342
11376
|
/**
|
|
11343
11377
|
* Reference to a computation in a mempool or executing pool.
|
|
@@ -11636,5 +11670,5 @@ declare function getRecoveryClusterAccAddress(mxeProgramId: PublicKey): PublicKe
|
|
|
11636
11670
|
*/
|
|
11637
11671
|
declare function getMxeRecoveryAccAddress(backupMxeProgramId: PublicKey, originalMxeProgramId: PublicKey): PublicKey;
|
|
11638
11672
|
|
|
11639
|
-
export { ARCIUM_ADDR, ARCIUM_IDL, Aes128Cipher, Aes192Cipher, Aes256Cipher, ArcisModule, ArcisType, CURVE25519_BASE_FIELD, CURVE25519_SCALAR_FIELD_MODULUS, Matrix, RescueCipher, RescueDesc, RescuePrimeHash, arcisEd25519, awaitComputationFinalization, buildFinalizeCompDefTx, deserializeLE, finalizeKeyRecoveryExecution, generateRandomFieldElem, getArciumAccountBaseSeed, getArciumEnv, getArciumProgram, getArciumProgramId, getArxNodeAccAddress, getClockAccAddress, getClusterAccAddress, getCompDefAccAddress, getCompDefAccOffset, getComputationAccAddress, getComputationsInMempool, getExecutingPoolAccAddress, getExecutingPoolAccInfo, getFeePoolAccAddress, getMXEAccAddress, getMXEArcisEd25519VerifyingKey, getMXEPublicKey, getMempoolAccAddress, getMempoolAccInfo, getMempoolPriorityFeeStats, getMxeRecoveryAccAddress, getRecoveryClusterAccAddress, initKeyRecoveryExecution, initMxePart1, initMxePart2, isNullRef, positiveModulo, queueKeyRecoveryInit, randMatrix, recoverMxe, serializeLE, sha256, submitKeyRecoveryShare, toVec, uploadCircuit };
|
|
11640
|
-
export type { Arcium as ArciumIdlType, ArciumLocalEnv, ComputationErrorType, ComputationReference, ExecutingPoolAccount, FpField, MempoolAccount, MempoolPriorityFeeStats };
|
|
11673
|
+
export { ARCIUM_ADDR, ARCIUM_IDL, Aes128Cipher, Aes192Cipher, Aes256Cipher, ArcisModule, ArcisType, ArcisValueField, CURVE25519_BASE_FIELD, CURVE25519_SCALAR_FIELD_MODULUS, IntegerInfo, Matrix, RescueCipher, RescueDesc, RescuePrimeHash, arcisEd25519, awaitComputationFinalization, buildFinalizeCompDefTx, createPacker, deserializeLE, finalizeKeyRecoveryExecution, generateRandomFieldElem, getArciumAccountBaseSeed, getArciumEnv, getArciumProgram, getArciumProgramId, getArxNodeAccAddress, getClockAccAddress, getClusterAccAddress, getCompDefAccAddress, getCompDefAccOffset, getComputationAccAddress, getComputationsInMempool, getExecutingPoolAccAddress, getExecutingPoolAccInfo, getFeePoolAccAddress, getMXEAccAddress, getMXEArcisEd25519VerifyingKey, getMXEPublicKey, getMempoolAccAddress, getMempoolAccInfo, getMempoolPriorityFeeStats, getMxeRecoveryAccAddress, getRecoveryClusterAccAddress, initKeyRecoveryExecution, initMxePart1, initMxePart2, isNullRef, positiveModulo, queueKeyRecoveryInit, randMatrix, recoverMxe, serializeLE, sha256, submitKeyRecoveryShare, toVec, uploadCircuit };
|
|
11674
|
+
export type { Arcium as ArciumIdlType, ArciumLocalEnv, ComputationErrorType, ComputationReference, ExecutingPoolAccount, FieldInfo, FpField, MempoolAccount, MempoolPriorityFeeStats, Packer };
|
package/build/index.mjs
CHANGED
|
@@ -262,6 +262,28 @@ function encodeAsRescueEncryptable(v) {
|
|
|
262
262
|
}
|
|
263
263
|
throw new Error('Invalid type to convert from number to bigint');
|
|
264
264
|
}
|
|
265
|
+
/**
|
|
266
|
+
* Decodes a Rescue-decrypted value back to a signed bigint.
|
|
267
|
+
* Handles the conversion from field element representation to signed integer.
|
|
268
|
+
* @param v - The decrypted field element value
|
|
269
|
+
* @returns The decoded signed bigint value
|
|
270
|
+
*/
|
|
271
|
+
function decodeRescueDecryptedToBigInt(v) {
|
|
272
|
+
const twoInv = (CURVE25519_BASE_FIELD.ORDER + 1n) / 2n;
|
|
273
|
+
const binSize = getBinSize(CURVE25519_BASE_FIELD.ORDER - 1n);
|
|
274
|
+
const isLtTwoInv = ctLt(v, twoInv, binSize);
|
|
275
|
+
return ctSelect(isLtTwoInv, v, ctSub(v, CURVE25519_BASE_FIELD.ORDER, binSize), binSize);
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Decodes a Rescue-decrypted value back to a JavaScript number.
|
|
279
|
+
* Converts from field element representation to a floating-point number.
|
|
280
|
+
* @param v - The decrypted field element value
|
|
281
|
+
* @returns The decoded number value
|
|
282
|
+
*/
|
|
283
|
+
function decodeRescueDecryptedToNumber(v) {
|
|
284
|
+
const vSigned = decodeRescueDecryptedToBigInt(v);
|
|
285
|
+
return Number(vSigned) * 2 ** -DOUBLE_PRECISION_MANTISSA;
|
|
286
|
+
}
|
|
265
287
|
/**
|
|
266
288
|
* Checks if a computation reference is null (all zeros).
|
|
267
289
|
* @param ref - The computation reference to check
|
|
@@ -1252,22 +1274,22 @@ class Aes256Cipher extends AesCtrCipher {
|
|
|
1252
1274
|
}
|
|
1253
1275
|
|
|
1254
1276
|
class DataSize {
|
|
1255
|
-
|
|
1277
|
+
isFull;
|
|
1256
1278
|
size;
|
|
1257
1279
|
index;
|
|
1258
1280
|
constructor(index, size) {
|
|
1259
|
-
const
|
|
1260
|
-
this.
|
|
1261
|
-
this.size =
|
|
1281
|
+
const isUndefined = size === undefined;
|
|
1282
|
+
this.isFull = isUndefined;
|
|
1283
|
+
this.size = isUndefined ? 0 : size;
|
|
1262
1284
|
this.index = index;
|
|
1263
1285
|
}
|
|
1264
1286
|
}
|
|
1265
1287
|
function sortDataSizes(arr) {
|
|
1266
|
-
arr.sort((left, right) => {
|
|
1267
|
-
if (left.
|
|
1268
|
-
return left.
|
|
1288
|
+
return [...arr].sort((left, right) => {
|
|
1289
|
+
if (left.isFull !== right.isFull) {
|
|
1290
|
+
return left.isFull ? -1 : 1;
|
|
1269
1291
|
}
|
|
1270
|
-
if (left.size
|
|
1292
|
+
if (left.size !== right.size) {
|
|
1271
1293
|
return right.size - left.size;
|
|
1272
1294
|
}
|
|
1273
1295
|
return left.index - right.index;
|
|
@@ -1290,7 +1312,7 @@ class PackingState {
|
|
|
1290
1312
|
this.maxSize = maxSize;
|
|
1291
1313
|
}
|
|
1292
1314
|
getCurrentLoad(index) {
|
|
1293
|
-
return this.loads[index]
|
|
1315
|
+
return this.loads[index] === undefined ? 0 : this.loads[index];
|
|
1294
1316
|
}
|
|
1295
1317
|
canFit(index, size) {
|
|
1296
1318
|
return this.getCurrentLoad(index) + size <= this.maxSize;
|
|
@@ -1305,7 +1327,7 @@ class PackingState {
|
|
|
1305
1327
|
return this.lastInsert + 1;
|
|
1306
1328
|
}
|
|
1307
1329
|
insert(size) {
|
|
1308
|
-
if (size.
|
|
1330
|
+
if (size.isFull) {
|
|
1309
1331
|
this.lastInsert = this.nFull;
|
|
1310
1332
|
this.nFull++;
|
|
1311
1333
|
return new PackLocation(this.lastInsert, 0);
|
|
@@ -1320,23 +1342,27 @@ class PackingState {
|
|
|
1320
1342
|
}
|
|
1321
1343
|
}
|
|
1322
1344
|
function packing(maxSize, arr) {
|
|
1323
|
-
sortDataSizes(arr);
|
|
1345
|
+
const sortedArr = sortDataSizes(arr);
|
|
1324
1346
|
const inserts = [];
|
|
1325
1347
|
const state = new PackingState(maxSize);
|
|
1326
|
-
|
|
1348
|
+
sortedArr.forEach((value) => {
|
|
1327
1349
|
const pack = state.insert(value);
|
|
1328
1350
|
inserts.push([value.index, pack]);
|
|
1329
1351
|
});
|
|
1330
|
-
const
|
|
1352
|
+
const nPacks = state.nFull + state.loads.length;
|
|
1331
1353
|
inserts.sort((left, right) => left[0] - right[0]);
|
|
1332
1354
|
const res = inserts.map((arg) => arg[1]);
|
|
1333
|
-
return [
|
|
1355
|
+
return [nPacks, res];
|
|
1334
1356
|
}
|
|
1335
1357
|
const ARCIS_PACKING_SIZE = 214;
|
|
1336
1358
|
function arcisPacking(arr) {
|
|
1337
1359
|
return packing(ARCIS_PACKING_SIZE, arr);
|
|
1338
1360
|
}
|
|
1339
1361
|
|
|
1362
|
+
/** Length of a Pubkey in bytes (Solana public keys are 32 bytes) */
|
|
1363
|
+
const PUBKEY_BYTE_LENGTH = 32;
|
|
1364
|
+
/** Maximum value a Pubkey bigint can hold (2^256) */
|
|
1365
|
+
const PUBKEY_MAX_VALUE = 1n << 256n;
|
|
1340
1366
|
var ArcisValueKind;
|
|
1341
1367
|
(function (ArcisValueKind) {
|
|
1342
1368
|
ArcisValueKind[ArcisValueKind["Integer"] = 0] = "Integer";
|
|
@@ -1358,10 +1384,10 @@ class IntegerInfo {
|
|
|
1358
1384
|
minValue() {
|
|
1359
1385
|
return this.signed ? -1n << (this.width - 1n) : 0n;
|
|
1360
1386
|
}
|
|
1361
|
-
|
|
1362
|
-
const
|
|
1363
|
-
const
|
|
1364
|
-
return
|
|
1387
|
+
isWithinBounds(b) {
|
|
1388
|
+
const minVal = this.minValue();
|
|
1389
|
+
const maxVal = this.signed ? 1n << (this.width - 1n) : 1n << this.width;
|
|
1390
|
+
return minVal <= b && b < maxVal;
|
|
1365
1391
|
}
|
|
1366
1392
|
name() {
|
|
1367
1393
|
return (this.signed ? "i" : "u") + this.width;
|
|
@@ -1395,9 +1421,9 @@ class ArcisValueField {
|
|
|
1395
1421
|
kind = ArcisValueKind.Pubkey;
|
|
1396
1422
|
break;
|
|
1397
1423
|
}
|
|
1398
|
-
if (kind
|
|
1399
|
-
if (typeof rawType
|
|
1400
|
-
throw TypeError("
|
|
1424
|
+
if (kind === ArcisValueKind.Integer) {
|
|
1425
|
+
if (typeof rawType === "string") {
|
|
1426
|
+
throw new TypeError("Expected Integer type object with signed/width properties");
|
|
1401
1427
|
}
|
|
1402
1428
|
const info = IntegerInfo.fromJson(rawType.Integer);
|
|
1403
1429
|
return new ArcisValueField(name, kind, info);
|
|
@@ -1407,38 +1433,63 @@ class ArcisValueField {
|
|
|
1407
1433
|
}
|
|
1408
1434
|
}
|
|
1409
1435
|
toBigInt(arg) {
|
|
1436
|
+
if (this.kind === ArcisValueKind.Float) {
|
|
1437
|
+
if (typeof arg !== 'number') {
|
|
1438
|
+
throw new TypeError(`Field ${this.name} expected a number, got ${typeof arg}`);
|
|
1439
|
+
}
|
|
1440
|
+
return encodeAsRescueEncryptable(arg);
|
|
1441
|
+
}
|
|
1442
|
+
let value = arg;
|
|
1443
|
+
if (typeof value === 'number') {
|
|
1444
|
+
if (!Number.isInteger(value)) {
|
|
1445
|
+
throw new TypeError(`Field ${this.name}: expected integer, got float ${value}`);
|
|
1446
|
+
}
|
|
1447
|
+
if (!Number.isSafeInteger(value)) {
|
|
1448
|
+
throw new RangeError(`Field ${this.name}: ${value} exceeds safe integer range, use BigInt`);
|
|
1449
|
+
}
|
|
1450
|
+
value = BigInt(value);
|
|
1451
|
+
}
|
|
1410
1452
|
switch (this.kind) {
|
|
1411
1453
|
case ArcisValueKind.Bool:
|
|
1412
|
-
if (typeof
|
|
1413
|
-
throw new TypeError(
|
|
1454
|
+
if (typeof value !== 'boolean') {
|
|
1455
|
+
throw new TypeError(`Field ${this.name} expected a boolean, got ${typeof value}`);
|
|
1414
1456
|
}
|
|
1415
|
-
return BigInt(
|
|
1416
|
-
case ArcisValueKind.Float:
|
|
1417
|
-
if (typeof arg != "number") {
|
|
1418
|
-
throw new TypeError("Field " + this.name + " expected a `number`, got `" + typeof arg + "`.");
|
|
1419
|
-
}
|
|
1420
|
-
return encodeAsRescueEncryptable(arg);
|
|
1457
|
+
return BigInt(value);
|
|
1421
1458
|
case ArcisValueKind.FullInteger:
|
|
1422
|
-
if (typeof
|
|
1423
|
-
throw new TypeError(
|
|
1459
|
+
if (typeof value !== 'bigint') {
|
|
1460
|
+
throw new TypeError(`Field ${this.name} expected a bigint, got ${typeof value}`);
|
|
1424
1461
|
}
|
|
1425
|
-
return
|
|
1462
|
+
return value;
|
|
1426
1463
|
case ArcisValueKind.Integer:
|
|
1427
|
-
if (typeof
|
|
1428
|
-
throw new TypeError(
|
|
1464
|
+
if (typeof value !== 'bigint') {
|
|
1465
|
+
throw new TypeError(`Field ${this.name} expected a bigint, got ${typeof value}`);
|
|
1429
1466
|
}
|
|
1430
|
-
if (
|
|
1431
|
-
throw new TypeError(
|
|
1467
|
+
if (this.info === undefined) {
|
|
1468
|
+
throw new TypeError(`Field ${this.name} is an integer, but signedness and width are unknown`);
|
|
1432
1469
|
}
|
|
1433
|
-
if (!this.info.
|
|
1434
|
-
|
|
1470
|
+
if (!this.info.isWithinBounds(value)) {
|
|
1471
|
+
const min = this.info.minValue();
|
|
1472
|
+
const max = this.info.signed ? (1n << (this.info.width - 1n)) - 1n : (1n << this.info.width) - 1n;
|
|
1473
|
+
throw new RangeError(`Field "${this.name}" (${this.info.name()}): value ${value} out of range [${min}, ${max}]`);
|
|
1435
1474
|
}
|
|
1436
|
-
return
|
|
1437
|
-
case ArcisValueKind.Pubkey:
|
|
1438
|
-
if (!(
|
|
1439
|
-
throw new TypeError(
|
|
1475
|
+
return value - this.info.minValue();
|
|
1476
|
+
case ArcisValueKind.Pubkey: {
|
|
1477
|
+
if (!(value instanceof Uint8Array)) {
|
|
1478
|
+
throw new TypeError(`Field ${this.name} expected a Uint8Array, got ${typeof value}`);
|
|
1440
1479
|
}
|
|
1441
|
-
|
|
1480
|
+
if (value.length !== PUBKEY_BYTE_LENGTH) {
|
|
1481
|
+
throw new RangeError(`Field ${this.name} expected ${PUBKEY_BYTE_LENGTH}-byte Uint8Array, got ${value.length} bytes`);
|
|
1482
|
+
}
|
|
1483
|
+
let pubkeyResult = 0n;
|
|
1484
|
+
for (let i = 0; i < PUBKEY_BYTE_LENGTH; i++) {
|
|
1485
|
+
pubkeyResult |= BigInt(value[i]) << BigInt(i * 8);
|
|
1486
|
+
}
|
|
1487
|
+
return pubkeyResult;
|
|
1488
|
+
}
|
|
1489
|
+
default: {
|
|
1490
|
+
const _exhaustive = this.kind;
|
|
1491
|
+
throw new Error(`Unhandled ArcisValueKind: ${_exhaustive}`);
|
|
1492
|
+
}
|
|
1442
1493
|
}
|
|
1443
1494
|
}
|
|
1444
1495
|
fromBigInt(arg) {
|
|
@@ -1450,21 +1501,58 @@ class ArcisValueField {
|
|
|
1450
1501
|
case 1n:
|
|
1451
1502
|
return true;
|
|
1452
1503
|
default:
|
|
1453
|
-
throw new
|
|
1504
|
+
throw new RangeError(`Field ${this.name}: Bool must be 0 or 1, got ${arg}`);
|
|
1454
1505
|
}
|
|
1455
1506
|
case ArcisValueKind.Float:
|
|
1456
|
-
return
|
|
1507
|
+
return decodeRescueDecryptedToNumber(arg);
|
|
1457
1508
|
case ArcisValueKind.FullInteger:
|
|
1458
1509
|
return arg;
|
|
1459
1510
|
case ArcisValueKind.Integer:
|
|
1460
|
-
if (this.info
|
|
1461
|
-
throw TypeError("Integer type without integer info");
|
|
1511
|
+
if (this.info === undefined) {
|
|
1512
|
+
throw new TypeError("Integer type without integer info");
|
|
1462
1513
|
}
|
|
1463
1514
|
return arg + this.info.minValue();
|
|
1464
|
-
case ArcisValueKind.Pubkey:
|
|
1465
|
-
|
|
1515
|
+
case ArcisValueKind.Pubkey: {
|
|
1516
|
+
if (arg < 0n) {
|
|
1517
|
+
throw new RangeError(`Field ${this.name}: Pubkey cannot be negative`);
|
|
1518
|
+
}
|
|
1519
|
+
if (arg >= PUBKEY_MAX_VALUE) {
|
|
1520
|
+
throw new RangeError(`Field ${this.name}: Pubkey exceeds 256 bits`);
|
|
1521
|
+
}
|
|
1522
|
+
const pubkeyBytes = new Uint8Array(PUBKEY_BYTE_LENGTH);
|
|
1523
|
+
let remaining = arg;
|
|
1524
|
+
for (let i = 0; i < PUBKEY_BYTE_LENGTH; i++) {
|
|
1525
|
+
pubkeyBytes[i] = Number(remaining & 0xffn);
|
|
1526
|
+
remaining >>= 8n;
|
|
1527
|
+
}
|
|
1528
|
+
return pubkeyBytes;
|
|
1529
|
+
}
|
|
1530
|
+
default: {
|
|
1531
|
+
const _exhaustive = this.kind;
|
|
1532
|
+
throw new Error(`Unhandled ArcisValueKind: ${_exhaustive}`);
|
|
1533
|
+
}
|
|
1466
1534
|
}
|
|
1467
1535
|
}
|
|
1536
|
+
static fromFieldInfo(info) {
|
|
1537
|
+
const name = info.name;
|
|
1538
|
+
if (info.type === 'Bool') {
|
|
1539
|
+
return new ArcisValueField(name, ArcisValueKind.Bool);
|
|
1540
|
+
}
|
|
1541
|
+
if (info.type === 'FullInteger') {
|
|
1542
|
+
return new ArcisValueField(name, ArcisValueKind.FullInteger);
|
|
1543
|
+
}
|
|
1544
|
+
if (info.type === 'Float') {
|
|
1545
|
+
return new ArcisValueField(name, ArcisValueKind.Float);
|
|
1546
|
+
}
|
|
1547
|
+
if (info.type === 'Pubkey') {
|
|
1548
|
+
return new ArcisValueField(name, ArcisValueKind.Pubkey);
|
|
1549
|
+
}
|
|
1550
|
+
if (typeof info.type === 'object' && 'Integer' in info.type) {
|
|
1551
|
+
const intInfo = new IntegerInfo(info.type.Integer.signed, BigInt(info.type.Integer.width));
|
|
1552
|
+
return new ArcisValueField(name, ArcisValueKind.Integer, intInfo);
|
|
1553
|
+
}
|
|
1554
|
+
throw new TypeError(`Unknown field type for ${name}`);
|
|
1555
|
+
}
|
|
1468
1556
|
toDataSize(index) {
|
|
1469
1557
|
switch (this.kind) {
|
|
1470
1558
|
case ArcisValueKind.Pubkey:
|
|
@@ -1488,6 +1576,9 @@ class ArcisType {
|
|
|
1488
1576
|
this.fields = fields;
|
|
1489
1577
|
}
|
|
1490
1578
|
pack(rawData) {
|
|
1579
|
+
if (rawData.length !== this.fields.length) {
|
|
1580
|
+
throw new RangeError(`Expected ${this.fields.length} fields, got ${rawData.length}`);
|
|
1581
|
+
}
|
|
1491
1582
|
const data = rawData.map((val, index) => this.fields[index].toBigInt(val));
|
|
1492
1583
|
const dataSizes = this.fields.map((field, index) => field.toDataSize(index));
|
|
1493
1584
|
const packing = arcisPacking(dataSizes);
|
|
@@ -1502,11 +1593,14 @@ class ArcisType {
|
|
|
1502
1593
|
unpack(packed) {
|
|
1503
1594
|
const dataSizes = this.fields.map((field, index) => field.toDataSize(index));
|
|
1504
1595
|
const packing = arcisPacking(dataSizes);
|
|
1596
|
+
if (packed.length < packing[0]) {
|
|
1597
|
+
throw new RangeError(`Expected at least ${packing[0]} packed elements, got ${packed.length}`);
|
|
1598
|
+
}
|
|
1505
1599
|
const res = [];
|
|
1506
1600
|
for (let idx = 0; idx < dataSizes.length; idx++) {
|
|
1507
1601
|
const packLocation = packing[1][idx];
|
|
1508
1602
|
const dataSize = dataSizes[idx];
|
|
1509
|
-
const val = dataSize.
|
|
1603
|
+
const val = dataSize.isFull ? packed[packLocation.index] : (packed[packLocation.index] >> BigInt(packLocation.offset)) % (1n << BigInt(dataSize.size));
|
|
1510
1604
|
res.push(this.fields[idx].fromBigInt(val));
|
|
1511
1605
|
}
|
|
1512
1606
|
return res;
|
|
@@ -1538,10 +1632,76 @@ class ArcisModule {
|
|
|
1538
1632
|
}
|
|
1539
1633
|
}
|
|
1540
1634
|
|
|
1541
|
-
|
|
1635
|
+
function parseFieldName(name) {
|
|
1636
|
+
const match = name.match(/^(.+)\[(\d+)\]$/);
|
|
1637
|
+
if (match) {
|
|
1638
|
+
return { base: match[1], index: parseInt(match[2], 10) };
|
|
1639
|
+
}
|
|
1640
|
+
return { base: name, index: null };
|
|
1641
|
+
}
|
|
1642
|
+
function extractValue(data, fieldName) {
|
|
1643
|
+
const { base, index } = parseFieldName(fieldName);
|
|
1644
|
+
const value = data[base];
|
|
1645
|
+
if (index !== null) {
|
|
1646
|
+
if (!Array.isArray(value)) {
|
|
1647
|
+
throw new TypeError(`Field "${base}" should be an array`);
|
|
1648
|
+
}
|
|
1649
|
+
if (index >= value.length) {
|
|
1650
|
+
throw new RangeError(`Field "${base}[${index}]" out of bounds (array length: ${value.length})`);
|
|
1651
|
+
}
|
|
1652
|
+
return value[index];
|
|
1653
|
+
}
|
|
1654
|
+
return value;
|
|
1655
|
+
}
|
|
1656
|
+
function groupUnpackedValues(values, fieldNames) {
|
|
1657
|
+
const result = {};
|
|
1658
|
+
for (let i = 0; i < fieldNames.length; i++) {
|
|
1659
|
+
const { base, index } = parseFieldName(fieldNames[i]);
|
|
1660
|
+
const value = values[i];
|
|
1661
|
+
if (index !== null) {
|
|
1662
|
+
if (!result[base]) {
|
|
1663
|
+
result[base] = [];
|
|
1664
|
+
}
|
|
1665
|
+
result[base][index] = value;
|
|
1666
|
+
}
|
|
1667
|
+
else {
|
|
1668
|
+
result[base] = value;
|
|
1669
|
+
}
|
|
1670
|
+
}
|
|
1671
|
+
return result;
|
|
1672
|
+
}
|
|
1673
|
+
/**
|
|
1674
|
+
* Creates a type-safe packer from field definitions.
|
|
1675
|
+
* Use `as const` on the fields array for compile-time field name validation.
|
|
1676
|
+
* @param fields - Field definitions from generated code.
|
|
1677
|
+
* @param typeName - Type name for debugging.
|
|
1678
|
+
*/
|
|
1679
|
+
function createPacker(fields, typeName = 'Packer') {
|
|
1680
|
+
const arcisFields = fields.map(f => ArcisValueField.fromFieldInfo(f));
|
|
1681
|
+
const arcisType = new ArcisType(typeName, arcisFields);
|
|
1682
|
+
const fieldNames = fields.map(f => f.name);
|
|
1683
|
+
return {
|
|
1684
|
+
pack(data) {
|
|
1685
|
+
const arr = fieldNames.map(name => {
|
|
1686
|
+
const value = extractValue(data, name);
|
|
1687
|
+
if (value === undefined) {
|
|
1688
|
+
throw new Error(`Missing required field: "${name}"`);
|
|
1689
|
+
}
|
|
1690
|
+
return value;
|
|
1691
|
+
});
|
|
1692
|
+
return arcisType.pack(arr);
|
|
1693
|
+
},
|
|
1694
|
+
unpack(packed) {
|
|
1695
|
+
const arr = arcisType.unpack(packed);
|
|
1696
|
+
return groupUnpackedValues(arr, fieldNames);
|
|
1697
|
+
}
|
|
1698
|
+
};
|
|
1699
|
+
}
|
|
1700
|
+
|
|
1701
|
+
var address = "Arcj82pX7HxYKLR92qvgZUAd7vGS1k4hQvAFcPATFdEQ";
|
|
1542
1702
|
var metadata = {
|
|
1543
1703
|
name: "arcium",
|
|
1544
|
-
version: "0.6.
|
|
1704
|
+
version: "0.6.1",
|
|
1545
1705
|
spec: "0.1.0",
|
|
1546
1706
|
description: "The Arcium program"
|
|
1547
1707
|
};
|
|
@@ -13422,4 +13582,4 @@ async function awaitEvent(eventListener, eventName, eventCheck, commitment = 'co
|
|
|
13422
13582
|
return { event: foundEvent[0], sig: foundEvent[1] };
|
|
13423
13583
|
}
|
|
13424
13584
|
|
|
13425
|
-
export { ARCIUM_ADDR, ARCIUM_IDL, Aes128Cipher, Aes192Cipher, Aes256Cipher, ArcisModule, ArcisType, CURVE25519_BASE_FIELD, CURVE25519_SCALAR_FIELD_MODULUS, Matrix, RescueCipher, RescueDesc, RescuePrimeHash, arcisEd25519, awaitComputationFinalization, buildFinalizeCompDefTx, deserializeLE, finalizeKeyRecoveryExecution, generateRandomFieldElem, getArciumAccountBaseSeed, getArciumEnv, getArciumProgram, getArciumProgramId, getArxNodeAccAddress, getClockAccAddress, getClusterAccAddress, getCompDefAccAddress, getCompDefAccOffset, getComputationAccAddress, getComputationsInMempool, getExecutingPoolAccAddress, getExecutingPoolAccInfo, getFeePoolAccAddress, getMXEAccAddress, getMXEArcisEd25519VerifyingKey, getMXEPublicKey, getMempoolAccAddress, getMempoolAccInfo, getMempoolPriorityFeeStats, getMxeRecoveryAccAddress, getRecoveryClusterAccAddress, initKeyRecoveryExecution, initMxePart1, initMxePart2, isNullRef, positiveModulo, queueKeyRecoveryInit, randMatrix, recoverMxe, serializeLE, sha256, submitKeyRecoveryShare, toVec, uploadCircuit };
|
|
13585
|
+
export { ARCIUM_ADDR, ARCIUM_IDL, Aes128Cipher, Aes192Cipher, Aes256Cipher, ArcisModule, ArcisType, ArcisValueField, CURVE25519_BASE_FIELD, CURVE25519_SCALAR_FIELD_MODULUS, IntegerInfo, Matrix, RescueCipher, RescueDesc, RescuePrimeHash, arcisEd25519, awaitComputationFinalization, buildFinalizeCompDefTx, createPacker, deserializeLE, finalizeKeyRecoveryExecution, generateRandomFieldElem, getArciumAccountBaseSeed, getArciumEnv, getArciumProgram, getArciumProgramId, getArxNodeAccAddress, getClockAccAddress, getClusterAccAddress, getCompDefAccAddress, getCompDefAccOffset, getComputationAccAddress, getComputationsInMempool, getExecutingPoolAccAddress, getExecutingPoolAccInfo, getFeePoolAccAddress, getMXEAccAddress, getMXEArcisEd25519VerifyingKey, getMXEPublicKey, getMempoolAccAddress, getMempoolAccInfo, getMempoolPriorityFeeStats, getMxeRecoveryAccAddress, getRecoveryClusterAccAddress, initKeyRecoveryExecution, initMxePart1, initMxePart2, isNullRef, positiveModulo, queueKeyRecoveryInit, randMatrix, recoverMxe, serializeLE, sha256, submitKeyRecoveryShare, toVec, uploadCircuit };
|