@interfold/sdk 0.13.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +51 -30
- package/dist/contracts/index.cjs +27 -12
- package/dist/contracts/index.cjs.map +1 -1
- package/dist/contracts/index.d.ts +2 -2
- package/dist/contracts/index.js +28 -12
- package/dist/contracts/index.js.map +1 -1
- package/dist/crypto/index.cjs.map +1 -1
- package/dist/crypto/index.js.map +1 -1
- package/dist/events/index.cjs +3 -0
- package/dist/events/index.cjs.map +1 -1
- package/dist/events/index.d.ts +24 -2
- package/dist/events/index.js +3 -0
- package/dist/events/index.js.map +1 -1
- package/dist/index.cjs +182 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +37 -9
- package/dist/index.js +180 -17
- package/dist/index.js.map +1 -1
- package/dist/{types-Cwx_flfX.d.ts → types-BJe3EYvv.d.ts} +8 -1
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
+
CommitteePublicKeyAssembler: () => CommitteePublicKeyAssembler,
|
|
33
34
|
CommitteeSize: () => CommitteeSize,
|
|
34
35
|
ContractClient: () => ContractClient,
|
|
35
36
|
DEFAULT_COMPUTE_PROVIDER_PARAMS: () => DEFAULT_COMPUTE_PROVIDER_PARAMS,
|
|
@@ -40,6 +41,8 @@ __export(index_exports, {
|
|
|
40
41
|
FailureReason: () => FailureReason,
|
|
41
42
|
InterfoldEventType: () => InterfoldEventType,
|
|
42
43
|
InterfoldSDK: () => InterfoldSDK,
|
|
44
|
+
MAX_COMMITTEE_PUBLIC_KEY_BYTES: () => MAX_COMMITTEE_PUBLIC_KEY_BYTES,
|
|
45
|
+
MAX_COMMITTEE_PUBLIC_KEY_CHUNK_BYTES: () => MAX_COMMITTEE_PUBLIC_KEY_CHUNK_BYTES,
|
|
43
46
|
RandomnessProviderEventType: () => RandomnessProviderEventType,
|
|
44
47
|
RegistryEventType: () => RegistryEventType,
|
|
45
48
|
SDKError: () => SDKError,
|
|
@@ -132,6 +135,15 @@ var DEFAULT_E3_CONFIG = {
|
|
|
132
135
|
payment_amount: "0"
|
|
133
136
|
// 0 ETH in wei
|
|
134
137
|
};
|
|
138
|
+
function cryptoConfigIdForParamSet(paramSet) {
|
|
139
|
+
if (paramSet === 0) {
|
|
140
|
+
return "0x04f3677e73b0f5066d6caf5cbd92e3fb2e38338edaf5cfc971ab28f7b684da78";
|
|
141
|
+
}
|
|
142
|
+
if (paramSet === 1) {
|
|
143
|
+
return "0xd9c86e581f8291ffb5b63595600e8d096ed30b16e2e0a6634a76c22b1f58fb4e";
|
|
144
|
+
}
|
|
145
|
+
throw new SDKError(`Unsupported BFV parameter set: ${paramSet}`, "UNSUPPORTED_CRYPTO_CONFIG");
|
|
146
|
+
}
|
|
135
147
|
function encodeBfvParams(params) {
|
|
136
148
|
const { degree, plaintextModulus, moduli, error1Variance } = params;
|
|
137
149
|
if (error1Variance === void 0) {
|
|
@@ -342,11 +354,7 @@ var ContractClient = class _ContractClient {
|
|
|
342
354
|
}
|
|
343
355
|
const committeeSize = validateCommitteeSize(params.committeeSize);
|
|
344
356
|
const maxFee = params.maxFee ?? await this.getE3Quote(params);
|
|
345
|
-
const expectedCryptoConfigId =
|
|
346
|
-
address: this.contracts.interfold,
|
|
347
|
-
abi: import_types.Interfold__factory.abi,
|
|
348
|
-
functionName: "activeCryptoConfigId"
|
|
349
|
-
});
|
|
357
|
+
const expectedCryptoConfigId = cryptoConfigIdForParamSet(params.paramSet);
|
|
350
358
|
const { request } = await this.publicClient.simulateContract({
|
|
351
359
|
address: this.contracts.interfold,
|
|
352
360
|
abi: import_types.Interfold__factory.abi,
|
|
@@ -393,7 +401,7 @@ var ContractClient = class _ContractClient {
|
|
|
393
401
|
throw new SDKError(`Failed to cancel E3: ${error}`, "CANCEL_E3_FAILED");
|
|
394
402
|
}
|
|
395
403
|
}
|
|
396
|
-
async publishCiphertextOutput(e3Id,
|
|
404
|
+
async publishCiphertextOutput(e3Id, outputReference, gasLimit) {
|
|
397
405
|
if (!this.walletClient) {
|
|
398
406
|
throw new SDKError("Wallet client required for write operations", "NO_WALLET");
|
|
399
407
|
}
|
|
@@ -402,11 +410,25 @@ var ContractClient = class _ContractClient {
|
|
|
402
410
|
if (!account) {
|
|
403
411
|
throw new SDKError("No account connected", "NO_ACCOUNT");
|
|
404
412
|
}
|
|
413
|
+
const encodedOutputReference = (0, import_viem2.encodeAbiParameters)(
|
|
414
|
+
[
|
|
415
|
+
{
|
|
416
|
+
type: "tuple",
|
|
417
|
+
components: [
|
|
418
|
+
{ name: "contentHash", type: "bytes32" },
|
|
419
|
+
{ name: "ciphertextCommitment", type: "bytes32" },
|
|
420
|
+
{ name: "computeProof", type: "bytes" },
|
|
421
|
+
{ name: "availabilityProof", type: "bytes" }
|
|
422
|
+
]
|
|
423
|
+
}
|
|
424
|
+
],
|
|
425
|
+
[outputReference]
|
|
426
|
+
);
|
|
405
427
|
const { request } = await this.publicClient.simulateContract({
|
|
406
428
|
address: this.contracts.interfold,
|
|
407
429
|
abi: import_types.Interfold__factory.abi,
|
|
408
430
|
functionName: "publishCiphertextOutput",
|
|
409
|
-
args: [e3Id,
|
|
431
|
+
args: [e3Id, encodedOutputReference],
|
|
410
432
|
account,
|
|
411
433
|
gas: gasLimit
|
|
412
434
|
});
|
|
@@ -431,11 +453,7 @@ var ContractClient = class _ContractClient {
|
|
|
431
453
|
async getE3Quote(requestParams) {
|
|
432
454
|
try {
|
|
433
455
|
const committeeSize = validateCommitteeSize(requestParams.committeeSize);
|
|
434
|
-
const expectedCryptoConfigId =
|
|
435
|
-
address: this.contracts.interfold,
|
|
436
|
-
abi: import_types.Interfold__factory.abi,
|
|
437
|
-
functionName: "activeCryptoConfigId"
|
|
438
|
-
});
|
|
456
|
+
const expectedCryptoConfigId = cryptoConfigIdForParamSet(requestParams.paramSet);
|
|
439
457
|
return this.publicClient.readContract({
|
|
440
458
|
address: this.contracts.interfold,
|
|
441
459
|
abi: import_types.Interfold__factory.abi,
|
|
@@ -536,6 +554,7 @@ var import_types3 = require("@interfold/contracts/types");
|
|
|
536
554
|
var InterfoldEventType = /* @__PURE__ */ ((InterfoldEventType2) => {
|
|
537
555
|
InterfoldEventType2["E3_REQUESTED"] = "E3Requested";
|
|
538
556
|
InterfoldEventType2["CIPHERTEXT_OUTPUT_PUBLISHED"] = "CiphertextOutputPublished";
|
|
557
|
+
InterfoldEventType2["CIPHERTEXT_OUTPUT_REFERENCE_PUBLISHED"] = "CiphertextOutputReferencePublished";
|
|
539
558
|
InterfoldEventType2["PLAINTEXT_OUTPUT_PUBLISHED"] = "PlaintextOutputPublished";
|
|
540
559
|
InterfoldEventType2["E3_PROGRAM_REGISTERED"] = "E3ProgramRegistered";
|
|
541
560
|
InterfoldEventType2["ENCRYPTION_SCHEME_ENABLED"] = "EncryptionSchemeEnabled";
|
|
@@ -551,6 +570,7 @@ var RegistryEventType = /* @__PURE__ */ ((RegistryEventType2) => {
|
|
|
551
570
|
RegistryEventType2["COMMITTEE_RANDOMNESS_REQUESTED"] = "CommitteeRandomnessRequested";
|
|
552
571
|
RegistryEventType2["RANDOMNESS_CIRCUIT_BREAKER_TRIPPED"] = "RandomnessCircuitBreakerTripped";
|
|
553
572
|
RegistryEventType2["COMMITTEE_PUBLISHED"] = "CommitteePublished";
|
|
573
|
+
RegistryEventType2["COMMITTEE_PUBLIC_KEY_CHUNK_PUBLISHED"] = "CommitteePublicKeyChunkPublished";
|
|
554
574
|
RegistryEventType2["COMMITTEE_FINALIZED"] = "SortitionCommitteeFinalized";
|
|
555
575
|
RegistryEventType2["INTERFOLD_SET"] = "InterfoldSet";
|
|
556
576
|
RegistryEventType2["OWNERSHIP_TRANSFERRED"] = "OwnershipTransferred";
|
|
@@ -590,6 +610,7 @@ var EventListener = class _EventListener {
|
|
|
590
610
|
"CommitteeRandomnessRequested" /* COMMITTEE_RANDOMNESS_REQUESTED */,
|
|
591
611
|
"RandomnessCircuitBreakerTripped" /* RANDOMNESS_CIRCUIT_BREAKER_TRIPPED */,
|
|
592
612
|
"CommitteePublished" /* COMMITTEE_PUBLISHED */,
|
|
613
|
+
"CommitteePublicKeyChunkPublished" /* COMMITTEE_PUBLIC_KEY_CHUNK_PUBLISHED */,
|
|
593
614
|
"SortitionCommitteeFinalized" /* COMMITTEE_FINALIZED */,
|
|
594
615
|
"InterfoldSet" /* INTERFOLD_SET */
|
|
595
616
|
]);
|
|
@@ -1189,9 +1210,9 @@ var InterfoldSDK = class _InterfoldSDK {
|
|
|
1189
1210
|
/**
|
|
1190
1211
|
* Validate serialized BFV public-key bytes before using them for encryption.
|
|
1191
1212
|
*
|
|
1192
|
-
*
|
|
1193
|
-
*
|
|
1194
|
-
*
|
|
1213
|
+
* A reassembled public key is an untrusted transport value. Consumers must
|
|
1214
|
+
* compare its semantic BFV commitment with the on-chain `pkCommitment`
|
|
1215
|
+
* before accepting it.
|
|
1195
1216
|
*/
|
|
1196
1217
|
async validatePublicKeyCommitment(publicKey, expectedCommitment) {
|
|
1197
1218
|
if (expectedCommitment.length !== 32) {
|
|
@@ -1231,8 +1252,8 @@ var InterfoldSDK = class _InterfoldSDK {
|
|
|
1231
1252
|
async getE3PublicKey(e3Id) {
|
|
1232
1253
|
return this.contractClient.getE3PublicKey(e3Id);
|
|
1233
1254
|
}
|
|
1234
|
-
async publishCiphertextOutput(e3Id,
|
|
1235
|
-
return this.contractClient.publishCiphertextOutput(e3Id,
|
|
1255
|
+
async publishCiphertextOutput(e3Id, outputReference, gasLimit) {
|
|
1256
|
+
return this.contractClient.publishCiphertextOutput(e3Id, outputReference, gasLimit);
|
|
1236
1257
|
}
|
|
1237
1258
|
async getE3(e3Id) {
|
|
1238
1259
|
return this.contractClient.getE3(e3Id);
|
|
@@ -1312,8 +1333,150 @@ var InterfoldSDK = class _InterfoldSDK {
|
|
|
1312
1333
|
});
|
|
1313
1334
|
}
|
|
1314
1335
|
};
|
|
1336
|
+
|
|
1337
|
+
// src/committee-public-key.ts
|
|
1338
|
+
var import_viem4 = require("viem");
|
|
1339
|
+
var MAX_COMMITTEE_PUBLIC_KEY_BYTES = 512 * 1024;
|
|
1340
|
+
var MAX_COMMITTEE_PUBLIC_KEY_CHUNK_BYTES = 90 * 1024;
|
|
1341
|
+
var DEFAULT_MAX_TRACKED_COMMITTEE_KEYS = 128;
|
|
1342
|
+
var CommitteePublicKeyAssembler = class {
|
|
1343
|
+
constructor(maxTrackedE3s = DEFAULT_MAX_TRACKED_COMMITTEE_KEYS) {
|
|
1344
|
+
this.maxTrackedE3s = maxTrackedE3s;
|
|
1345
|
+
if (!Number.isInteger(maxTrackedE3s) || maxTrackedE3s < 1) {
|
|
1346
|
+
throw new Error("Maximum tracked committee-key count must be a positive integer");
|
|
1347
|
+
}
|
|
1348
|
+
}
|
|
1349
|
+
selectedCandidates = /* @__PURE__ */ new Map();
|
|
1350
|
+
assemblies = /* @__PURE__ */ new Map();
|
|
1351
|
+
invalidAssemblies = /* @__PURE__ */ new Set();
|
|
1352
|
+
completedAssemblies = /* @__PURE__ */ new Set();
|
|
1353
|
+
trackedE3s = /* @__PURE__ */ new Map();
|
|
1354
|
+
add(event) {
|
|
1355
|
+
const e3Key = event.e3Id.toString();
|
|
1356
|
+
this.track(e3Key);
|
|
1357
|
+
const metadata = validateEvent(event);
|
|
1358
|
+
const publisherKey = `${e3Key}:${event.publisher.toLowerCase()}`;
|
|
1359
|
+
const selectedCandidate = this.selectedCandidates.get(publisherKey);
|
|
1360
|
+
if (selectedCandidate && selectedCandidate.toLowerCase() !== metadata.candidateHash.toLowerCase()) {
|
|
1361
|
+
return void 0;
|
|
1362
|
+
}
|
|
1363
|
+
this.selectedCandidates.set(publisherKey, metadata.candidateHash);
|
|
1364
|
+
const assemblyKey = `${publisherKey}:${metadata.candidateHash.toLowerCase()}`;
|
|
1365
|
+
if (this.completedAssemblies.has(assemblyKey)) return void 0;
|
|
1366
|
+
if (this.invalidAssemblies.has(assemblyKey)) return void 0;
|
|
1367
|
+
const assembly = this.assemblies.get(assemblyKey) ?? {
|
|
1368
|
+
nodes: [...event.nodes],
|
|
1369
|
+
pkCommitment: metadata.pkCommitment,
|
|
1370
|
+
candidateHash: metadata.candidateHash,
|
|
1371
|
+
totalLength: event.totalLength,
|
|
1372
|
+
chunks: Array.from({ length: event.chunkCount }).fill(void 0)
|
|
1373
|
+
};
|
|
1374
|
+
if (!metadataMatches(assembly, event, metadata.pkCommitment)) {
|
|
1375
|
+
this.assemblies.delete(assemblyKey);
|
|
1376
|
+
this.invalidAssemblies.add(assemblyKey);
|
|
1377
|
+
return void 0;
|
|
1378
|
+
}
|
|
1379
|
+
const existing = assembly.chunks[event.chunkIndex];
|
|
1380
|
+
if (existing && !bytesEqual(existing, metadata.chunk)) {
|
|
1381
|
+
this.assemblies.delete(assemblyKey);
|
|
1382
|
+
this.invalidAssemblies.add(assemblyKey);
|
|
1383
|
+
return void 0;
|
|
1384
|
+
}
|
|
1385
|
+
assembly.chunks[event.chunkIndex] = metadata.chunk;
|
|
1386
|
+
this.assemblies.set(assemblyKey, assembly);
|
|
1387
|
+
if (assembly.chunks.some((chunk) => chunk === void 0)) return void 0;
|
|
1388
|
+
const publicKey = new Uint8Array(assembly.totalLength);
|
|
1389
|
+
let offset = 0;
|
|
1390
|
+
for (const chunk of assembly.chunks) {
|
|
1391
|
+
publicKey.set(chunk, offset);
|
|
1392
|
+
offset += chunk.length;
|
|
1393
|
+
}
|
|
1394
|
+
if (offset !== assembly.totalLength || (0, import_viem4.keccak256)(publicKey).toLowerCase() !== assembly.candidateHash.toLowerCase()) {
|
|
1395
|
+
this.assemblies.delete(assemblyKey);
|
|
1396
|
+
this.invalidAssemblies.add(assemblyKey);
|
|
1397
|
+
return void 0;
|
|
1398
|
+
}
|
|
1399
|
+
this.completedAssemblies.add(assemblyKey);
|
|
1400
|
+
this.assemblies.delete(assemblyKey);
|
|
1401
|
+
return {
|
|
1402
|
+
e3Id: event.e3Id,
|
|
1403
|
+
nodes: assembly.nodes,
|
|
1404
|
+
pkCommitment: assembly.pkCommitment,
|
|
1405
|
+
publicKey
|
|
1406
|
+
};
|
|
1407
|
+
}
|
|
1408
|
+
clear(e3Id) {
|
|
1409
|
+
const e3Key = e3Id.toString();
|
|
1410
|
+
this.trackedE3s.delete(e3Key);
|
|
1411
|
+
this.dropE3(e3Key);
|
|
1412
|
+
}
|
|
1413
|
+
track(e3Key) {
|
|
1414
|
+
this.trackedE3s.delete(e3Key);
|
|
1415
|
+
this.trackedE3s.set(e3Key, true);
|
|
1416
|
+
while (this.trackedE3s.size > this.maxTrackedE3s) {
|
|
1417
|
+
const oldest = this.trackedE3s.keys().next().value;
|
|
1418
|
+
if (oldest === void 0) return;
|
|
1419
|
+
this.trackedE3s.delete(oldest);
|
|
1420
|
+
this.dropE3(oldest);
|
|
1421
|
+
}
|
|
1422
|
+
}
|
|
1423
|
+
dropE3(e3Key) {
|
|
1424
|
+
const prefix = `${e3Key}:`;
|
|
1425
|
+
for (const key of this.selectedCandidates.keys()) {
|
|
1426
|
+
if (key.startsWith(prefix)) this.selectedCandidates.delete(key);
|
|
1427
|
+
}
|
|
1428
|
+
for (const key of this.assemblies.keys()) {
|
|
1429
|
+
if (key.startsWith(prefix)) this.assemblies.delete(key);
|
|
1430
|
+
}
|
|
1431
|
+
for (const key of this.invalidAssemblies) {
|
|
1432
|
+
if (key.startsWith(prefix)) this.invalidAssemblies.delete(key);
|
|
1433
|
+
}
|
|
1434
|
+
for (const key of this.completedAssemblies) {
|
|
1435
|
+
if (key.startsWith(prefix)) this.completedAssemblies.delete(key);
|
|
1436
|
+
}
|
|
1437
|
+
}
|
|
1438
|
+
};
|
|
1439
|
+
function validateEvent(event) {
|
|
1440
|
+
if (!isBytes32(event.candidateHash) || !isBytes32(event.pkCommitment)) {
|
|
1441
|
+
throw new Error("Committee public-key chunk contains an invalid bytes32 value");
|
|
1442
|
+
}
|
|
1443
|
+
if (!Number.isInteger(event.totalLength) || event.totalLength <= 0 || event.totalLength > MAX_COMMITTEE_PUBLIC_KEY_BYTES) {
|
|
1444
|
+
throw new Error("Committee public-key total length is outside the supported range");
|
|
1445
|
+
}
|
|
1446
|
+
const expectedChunkCount = Math.ceil(event.totalLength / MAX_COMMITTEE_PUBLIC_KEY_CHUNK_BYTES);
|
|
1447
|
+
if (!Number.isInteger(event.chunkCount) || event.chunkCount !== expectedChunkCount) {
|
|
1448
|
+
throw new Error("Committee public-key chunk count does not match the total length");
|
|
1449
|
+
}
|
|
1450
|
+
if (!Number.isInteger(event.chunkIndex) || event.chunkIndex < 0 || event.chunkIndex >= event.chunkCount) {
|
|
1451
|
+
throw new Error("Committee public-key chunk index is outside the candidate range");
|
|
1452
|
+
}
|
|
1453
|
+
if (!(0, import_viem4.isHex)(event.chunk)) {
|
|
1454
|
+
throw new Error("Committee public-key chunk is not valid hex");
|
|
1455
|
+
}
|
|
1456
|
+
const chunk = (0, import_viem4.hexToBytes)(event.chunk);
|
|
1457
|
+
const remaining = event.totalLength - event.chunkIndex * MAX_COMMITTEE_PUBLIC_KEY_CHUNK_BYTES;
|
|
1458
|
+
const expectedLength = Math.min(remaining, MAX_COMMITTEE_PUBLIC_KEY_CHUNK_BYTES);
|
|
1459
|
+
if (chunk.length !== expectedLength) {
|
|
1460
|
+
throw new Error("Committee public-key chunk length does not match its index");
|
|
1461
|
+
}
|
|
1462
|
+
return {
|
|
1463
|
+
candidateHash: event.candidateHash,
|
|
1464
|
+
pkCommitment: event.pkCommitment,
|
|
1465
|
+
chunk
|
|
1466
|
+
};
|
|
1467
|
+
}
|
|
1468
|
+
function metadataMatches(assembly, event, pkCommitment) {
|
|
1469
|
+
return assembly.totalLength === event.totalLength && assembly.chunks.length === event.chunkCount && assembly.pkCommitment.toLowerCase() === pkCommitment.toLowerCase() && assembly.nodes.length === event.nodes.length && assembly.nodes.every((node, index) => node.toLowerCase() === event.nodes[index]?.toLowerCase());
|
|
1470
|
+
}
|
|
1471
|
+
function isBytes32(value) {
|
|
1472
|
+
return /^0x[0-9a-fA-F]{64}$/.test(value);
|
|
1473
|
+
}
|
|
1474
|
+
function bytesEqual(left, right) {
|
|
1475
|
+
return left.length === right.length && left.every((byte, index) => byte === right[index]);
|
|
1476
|
+
}
|
|
1315
1477
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1316
1478
|
0 && (module.exports = {
|
|
1479
|
+
CommitteePublicKeyAssembler,
|
|
1317
1480
|
CommitteeSize,
|
|
1318
1481
|
ContractClient,
|
|
1319
1482
|
DEFAULT_COMPUTE_PROVIDER_PARAMS,
|
|
@@ -1324,6 +1487,8 @@ var InterfoldSDK = class _InterfoldSDK {
|
|
|
1324
1487
|
FailureReason,
|
|
1325
1488
|
InterfoldEventType,
|
|
1326
1489
|
InterfoldSDK,
|
|
1490
|
+
MAX_COMMITTEE_PUBLIC_KEY_BYTES,
|
|
1491
|
+
MAX_COMMITTEE_PUBLIC_KEY_CHUNK_BYTES,
|
|
1327
1492
|
RandomnessProviderEventType,
|
|
1328
1493
|
RegistryEventType,
|
|
1329
1494
|
SDKError,
|