@crisp-e3/sdk 0.5.12 → 0.7.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.
@@ -0,0 +1,2 @@
1
+
2
+ export { }
@@ -0,0 +1,144 @@
1
+ // src/encoding.ts
2
+ import { ZKInputsGenerator as ZKInputsGenerator2 } from "@crisp-e3/zk-inputs";
3
+
4
+ // src/utils.ts
5
+ import { poseidon2 } from "poseidon-lite";
6
+ import { LeanIMT } from "@zk-kit/lean-imt";
7
+
8
+ // src/constants.ts
9
+ import { hashMessage } from "viem";
10
+ var MAX_VOTE_BITS = 50;
11
+ var SIGNATURE_MESSAGE = "CRISP: Sign this message to prove ownership of your Ethereum account";
12
+ var SIGNATURE_MESSAGE_HASH = hashMessage(SIGNATURE_MESSAGE);
13
+
14
+ // src/utils.ts
15
+ import { publicKeyToAddress } from "viem/utils";
16
+ import { hexToBytes, recoverPublicKey } from "viem";
17
+ import { ZKInputsGenerator } from "@crisp-e3/zk-inputs";
18
+ var toBinary = (number) => {
19
+ if (number < 0) {
20
+ throw new Error("Value cannot be negative");
21
+ }
22
+ return number.toString(2);
23
+ };
24
+ var extractSignatureComponents = async (signature, messageHash = SIGNATURE_MESSAGE_HASH) => {
25
+ const publicKey = await recoverPublicKey({ hash: messageHash, signature });
26
+ const publicKeyBytes = hexToBytes(publicKey);
27
+ const publicKeyX = publicKeyBytes.slice(1, 33);
28
+ const publicKeyY = publicKeyBytes.slice(33, 65);
29
+ const sigBytes = hexToBytes(signature);
30
+ const r = sigBytes.slice(0, 32);
31
+ const s = sigBytes.slice(32, 64);
32
+ const signatureBytes = new Uint8Array(64);
33
+ signatureBytes.set(r, 0);
34
+ signatureBytes.set(s, 32);
35
+ return {
36
+ messageHash: hexToBytes(messageHash),
37
+ publicKeyX,
38
+ publicKeyY,
39
+ signature: signatureBytes
40
+ };
41
+ };
42
+ var getZeroVote = (numChoices) => {
43
+ return Array(numChoices).fill(0);
44
+ };
45
+ var numberArrayToBigInt64Array = (numberArray) => {
46
+ return BigInt64Array.from(numberArray.map(BigInt));
47
+ };
48
+
49
+ // src/encoding.ts
50
+ import { hexToBytes as hexToBytes2 } from "viem";
51
+ var _zkInputsGenerator = null;
52
+ var getZkInputsGenerator = () => {
53
+ if (!_zkInputsGenerator) {
54
+ _zkInputsGenerator = ZKInputsGenerator2.withDefaults();
55
+ }
56
+ return _zkInputsGenerator;
57
+ };
58
+ var encodeVote = (vote) => {
59
+ if (vote.length < 2) {
60
+ throw new Error("Vote must have at least two choices");
61
+ }
62
+ const bfvParams = getZkInputsGenerator().getBFVParams();
63
+ const degree = bfvParams.degree;
64
+ const n = vote.length;
65
+ const segmentSize = Math.floor(degree / n);
66
+ const maxBits = Math.min(segmentSize, MAX_VOTE_BITS);
67
+ const maxValue = 2 ** maxBits - 1;
68
+ const voteArray = [];
69
+ for (let choiceIdx = 0; choiceIdx < n; choiceIdx += 1) {
70
+ const value = choiceIdx < vote.length ? vote[choiceIdx] : 0;
71
+ if (value > maxValue) {
72
+ throw new Error(`Vote value for choice ${choiceIdx} exceeds maximum (${maxValue})`);
73
+ }
74
+ const binary = toBinary(value).split("");
75
+ for (let i = 0; i < segmentSize; i += 1) {
76
+ const offset = segmentSize - binary.length;
77
+ voteArray.push(i < offset ? 0 : parseInt(binary[i - offset]));
78
+ }
79
+ }
80
+ const remainder = degree - segmentSize * n;
81
+ for (let i = 0; i < remainder; i++) {
82
+ voteArray.push(0);
83
+ }
84
+ return voteArray;
85
+ };
86
+ var encryptVote = (vote, publicKey) => {
87
+ const encodedVote = encodeVote(vote);
88
+ return getZkInputsGenerator().encryptVote(publicKey, numberArrayToBigInt64Array(encodedVote));
89
+ };
90
+
91
+ // src/circuitInputs.ts
92
+ var generateCircuitInputsImpl = async (proofInputs) => {
93
+ const zkInputsGenerator = getZkInputsGenerator();
94
+ const numOptions = proofInputs.vote.length;
95
+ const zeroVote = getZeroVote(numOptions);
96
+ const encodedVote = encodeVote(proofInputs.vote);
97
+ let circuitInputs;
98
+ let encryptedVote;
99
+ if (!proofInputs.previousCiphertext) {
100
+ const result = await zkInputsGenerator.generateInputs(
101
+ encryptVote(zeroVote, proofInputs.publicKey),
102
+ proofInputs.publicKey,
103
+ numberArrayToBigInt64Array(encodedVote)
104
+ );
105
+ circuitInputs = result.inputs;
106
+ encryptedVote = result.encryptedVote;
107
+ } else {
108
+ const result = await zkInputsGenerator.generateInputsForUpdate(
109
+ proofInputs.previousCiphertext,
110
+ proofInputs.publicKey,
111
+ numberArrayToBigInt64Array(encodedVote)
112
+ );
113
+ circuitInputs = result.inputs;
114
+ encryptedVote = result.encryptedVote;
115
+ }
116
+ const signature = await extractSignatureComponents(proofInputs.signature, proofInputs.messageHash);
117
+ circuitInputs.hashed_message = Array.from(signature.messageHash).map((b) => b.toString());
118
+ circuitInputs.public_key_x = Array.from(signature.publicKeyX).map((b) => b.toString());
119
+ circuitInputs.public_key_y = Array.from(signature.publicKeyY).map((b) => b.toString());
120
+ circuitInputs.signature = Array.from(signature.signature).map((b) => b.toString());
121
+ circuitInputs.slot_address = proofInputs.slotAddress.toLowerCase();
122
+ circuitInputs.balance = proofInputs.balance.toString();
123
+ circuitInputs.is_first_vote = !proofInputs.previousCiphertext;
124
+ circuitInputs.is_mask_vote = proofInputs.isMaskVote;
125
+ circuitInputs.merkle_root = proofInputs.merkleProof.proof.root.toString();
126
+ circuitInputs.merkle_proof_length = proofInputs.merkleProof.length.toString();
127
+ circuitInputs.merkle_proof_indices = proofInputs.merkleProof.indices.map((i) => i.toString());
128
+ circuitInputs.merkle_proof_siblings = proofInputs.merkleProof.proof.siblings.map((s) => s.toString());
129
+ circuitInputs.num_options = numOptions.toString();
130
+ return { circuitInputs, encryptedVote };
131
+ };
132
+
133
+ // src/workers/generateCircuitInputs.worker.ts
134
+ self.onmessage = async (e) => {
135
+ try {
136
+ const result = await generateCircuitInputsImpl(e.data);
137
+ self.postMessage({ type: "result", ...result });
138
+ } catch (err) {
139
+ const error = err instanceof Error ? err.message : String(err);
140
+ const stack = err instanceof Error ? err.stack : void 0;
141
+ self.postMessage({ type: "error", error, stack });
142
+ }
143
+ };
144
+ //# sourceMappingURL=generateCircuitInputs.worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/encoding.ts","../../src/utils.ts","../../src/constants.ts","../../src/circuitInputs.ts","../../src/workers/generateCircuitInputs.worker.ts"],"sourcesContent":["// SPDX-License-Identifier: LGPL-3.0-only\n//\n// This file is provided WITHOUT ANY WARRANTY;\n// without even the implied warranty of MERCHANTABILITY\n// or FITNESS FOR A PARTICULAR PURPOSE.\n\n/**\n * Vote encoding and BFV encryption for the CRISP voting protocol.\n *\n * Encodes vote choices (numbers per option) into polynomial coefficient arrays\n * suitable for BFV homomorphic encryption. Each choice is represented as a\n * segment of binary digits, padded to fit the polynomial degree. Supports\n * encoding, encryption, decryption, and tally decoding.\n */\n\nimport { ZKInputsGenerator } from '@crisp-e3/zk-inputs'\nimport { toBinary, numberArrayToBigInt64Array, decodeBytesToNumbers } from './utils'\nimport { MAX_VOTE_BITS } from './constants'\nimport { hexToBytes } from 'viem'\nimport type { Hex } from 'viem'\nimport type { Vote } from './types'\n\nlet _zkInputsGenerator: InstanceType<typeof ZKInputsGenerator> | null = null\n\n/**\n * Returns the singleton ZK inputs generator instance (lazily initialized).\n */\nexport const getZkInputsGenerator = () => {\n if (!_zkInputsGenerator) {\n _zkInputsGenerator = ZKInputsGenerator.withDefaults()\n }\n return _zkInputsGenerator\n}\n\n/**\n * Encodes vote choices into a polynomial coefficient array for BFV encryption.\n * Each choice is split into a segment of binary digits; segments are padded\n * to align with the polynomial degree.\n *\n * @param vote - Array of numeric values per choice (e.g. [10, 5] for 2 options)\n * @returns Array of 0s and 1s representing coefficients\n * @throws If vote has fewer than 2 choices or any value exceeds max bits\n */\nexport const encodeVote = (vote: Vote): number[] => {\n if (vote.length < 2) {\n throw new Error('Vote must have at least two choices')\n }\n\n const bfvParams = getZkInputsGenerator().getBFVParams()\n const degree = bfvParams.degree\n const n = vote.length\n\n const segmentSize = Math.floor(degree / n)\n const maxBits = Math.min(segmentSize, MAX_VOTE_BITS)\n const maxValue = 2 ** maxBits - 1\n const voteArray: number[] = []\n\n for (let choiceIdx = 0; choiceIdx < n; choiceIdx += 1) {\n const value = choiceIdx < vote.length ? vote[choiceIdx] : 0\n\n if (value > maxValue) {\n throw new Error(`Vote value for choice ${choiceIdx} exceeds maximum (${maxValue})`)\n }\n\n const binary = toBinary(value).split('')\n\n for (let i = 0; i < segmentSize; i += 1) {\n const offset = segmentSize - binary.length\n voteArray.push(i < offset ? 0 : parseInt(binary[i - offset]))\n }\n }\n\n const remainder = degree - segmentSize * n\n for (let i = 0; i < remainder; i++) {\n voteArray.push(0)\n }\n\n return voteArray\n}\n\n/**\n * Encrypts an encoded vote using BFV homomorphic encryption.\n *\n * @param vote - Vote choices to encrypt\n * @param publicKey - BFV public key\n * @returns Encrypted ciphertext\n */\nexport const encryptVote = (vote: Vote, publicKey: Uint8Array): Uint8Array => {\n const encodedVote = encodeVote(vote)\n\n return getZkInputsGenerator().encryptVote(publicKey, numberArrayToBigInt64Array(encodedVote))\n}\n\n/**\n * Decodes raw tally bytes (or hex string) into vote values per choice.\n * Expects the same segment layout as used in encodeVote.\n *\n * @param tallyBytes - Hex string or array of decoded numbers from tally/decryption\n * @param numChoices - Number of vote options\n * @returns Vote array with one value per choice\n */\nexport const decodeTally = (tallyBytes: string | number[], numChoices: number): Vote => {\n if (typeof tallyBytes === 'string') {\n const hexString = tallyBytes.startsWith('0x') ? tallyBytes : `0x${tallyBytes}`\n tallyBytes = decodeBytesToNumbers(hexToBytes(hexString as Hex))\n }\n\n if (numChoices <= 0) {\n throw new Error('Number of choices must be positive')\n }\n\n const segmentSize = Math.floor(tallyBytes.length / numChoices)\n const effectiveSize = Math.min(segmentSize, MAX_VOTE_BITS)\n const results: Vote = []\n\n for (let choiceIdx = 0; choiceIdx < numChoices; choiceIdx++) {\n const segmentStart = choiceIdx * segmentSize\n const readStart = segmentStart + segmentSize - effectiveSize\n const segment = tallyBytes.slice(readStart, readStart + effectiveSize)\n\n let value = 0\n for (let i = 0; i < segment.length; i++) {\n const weight = 2 ** (segment.length - 1 - i)\n value += segment[i] * weight\n }\n\n results.push(value)\n }\n\n return results\n}\n\n/**\n * Decrypts a BFV-encrypted vote and decodes it to vote values.\n *\n * @param ciphertext - Encrypted vote\n * @param secretKey - BFV secret key\n * @param numChoices - Number of vote options\n * @returns Decrypted vote array\n */\nexport const decryptVote = (ciphertext: Uint8Array, secretKey: Uint8Array, numChoices: number): Vote => {\n const decryptedVote = getZkInputsGenerator().decryptVote(secretKey, ciphertext)\n\n return decodeTally(\n Array.from(decryptedVote).map((v) => Number(v)),\n numChoices,\n )\n}\n\n/**\n * Generates a BFV keypair for vote encryption and decryption.\n *\n * @returns Object with secretKey and publicKey as Uint8Arrays\n */\nexport const generateBFVKeys = (): { secretKey: Uint8Array; publicKey: Uint8Array } => {\n return getZkInputsGenerator().generateKeys()\n}\n","// SPDX-License-Identifier: LGPL-3.0-only\n//\n// This file is provided WITHOUT ANY WARRANTY;\n// without even the implied warranty of MERCHANTABILITY\n// or FITNESS FOR A PARTICULAR PURPOSE.\n\nimport { poseidon2 } from 'poseidon-lite'\nimport { LeanIMT } from '@zk-kit/lean-imt'\nimport type { MerkleProof } from './types'\nimport { MAX_VOTE_BITS, MERKLE_TREE_MAX_DEPTH, SIGNATURE_MESSAGE_HASH } from './constants'\nimport { publicKeyToAddress } from 'viem/utils'\nimport { hexToBytes, recoverPublicKey } from 'viem'\nimport { ZKInputsGenerator } from '@crisp-e3/zk-inputs'\n\n/**\n * Hash a leaf node for the Merkle tree\n * @param address The voter's address\n * @param balance The voter's balance\n * @returns The hashed leaf as a bigint\n */\nexport const hashLeaf = (address: string, balance: bigint): bigint => {\n return poseidon2([address.toLowerCase(), balance])\n}\n\n/**\n * Generate a new LeanIMT with the leaves provided\n * @param leaves The leaves of the Merkle tree\n * @returns the generated Merkle tree\n */\nexport const generateMerkleTree = (leaves: bigint[]): LeanIMT => {\n return new LeanIMT((a, b) => poseidon2([a, b]), leaves)\n}\n\n/**\n * Generate a Merkle proof for a given address to prove inclusion in the voters' list\n * @param balance The voter's balance\n * @param address The voter's address\n * @param leaves The leaves of the Merkle tree\n */\nexport const generateMerkleProof = (balance: bigint, address: string, leaves: bigint[] | string[]): MerkleProof => {\n const leaf = hashLeaf(address.toLowerCase(), balance)\n\n const index = leaves.findIndex((l) => BigInt(l) === leaf)\n\n if (index === -1) {\n throw new Error('Leaf not found in the tree')\n }\n\n const tree = generateMerkleTree(leaves.map((l) => BigInt(l)))\n\n const proof = tree.generateProof(index)\n\n // Pad siblings with zeros\n const paddedSiblings = [...proof.siblings, ...Array(MERKLE_TREE_MAX_DEPTH - proof.siblings.length).fill(0n)]\n // Pad indices with zeros\n const indices = proof.siblings.map((_, i) => Number((BigInt(proof.index) >> BigInt(i)) & 1n))\n const paddedIndices = [...indices, ...Array(MERKLE_TREE_MAX_DEPTH - indices.length).fill(0)]\n\n return {\n leaf,\n index,\n proof: {\n ...proof,\n siblings: paddedSiblings,\n },\n // Original length before padding\n length: proof.siblings.length,\n indices: paddedIndices,\n }\n}\n\n/**\n * Convert a number to its binary representation\n * @param number The number to convert to binary\n * @returns The binary representation of the number as a string\n */\nexport const toBinary = (number: number): string => {\n if (number < 0) {\n throw new Error('Value cannot be negative')\n }\n\n return number.toString(2)\n}\n\n/**\n * Given a signature, extract the signature components for the Noir signature verification circuit.\n * @param signature The signature to extract the components from.\n * @returns The extracted signature components.\n */\nexport const extractSignatureComponents = async (\n signature: `0x${string}`,\n messageHash: `0x${string}` = SIGNATURE_MESSAGE_HASH,\n): Promise<{\n messageHash: Uint8Array\n publicKeyX: Uint8Array\n publicKeyY: Uint8Array\n signature: Uint8Array\n}> => {\n const publicKey = await recoverPublicKey({ hash: messageHash, signature })\n const publicKeyBytes = hexToBytes(publicKey)\n const publicKeyX = publicKeyBytes.slice(1, 33)\n const publicKeyY = publicKeyBytes.slice(33, 65)\n\n // Extract r and s from signature (remove v)\n const sigBytes = hexToBytes(signature)\n const r = sigBytes.slice(0, 32) // First 32 bytes\n const s = sigBytes.slice(32, 64) // Next 32 bytes\n\n const signatureBytes = new Uint8Array(64)\n signatureBytes.set(r, 0)\n signatureBytes.set(s, 32)\n\n return {\n messageHash: hexToBytes(messageHash),\n publicKeyX: publicKeyX,\n publicKeyY: publicKeyY,\n signature: signatureBytes,\n }\n}\n\nexport const getAddressFromSignature = async (signature: `0x${string}`, messageHash?: `0x${string}`): Promise<string> => {\n const publicKey = await recoverPublicKey({ hash: messageHash || SIGNATURE_MESSAGE_HASH, signature })\n\n return publicKeyToAddress(publicKey)\n}\n\n/**\n * Get the maximum vote value for a given number of choices.\n * @param numChoices Number of choices.\n * @returns Maximum value per choice.\n */\nexport const getMaxVoteValue = (numChoices: number): number => {\n const bfvParams = ZKInputsGenerator.withDefaults().getBFVParams()\n const segmentSize = Math.floor(bfvParams.degree / numChoices)\n const effectiveBits = Math.min(segmentSize, MAX_VOTE_BITS)\n return 2 ** effectiveBits - 1\n}\n\n/**\n * Get a zero vote with the given number of choices.\n * @param numChoices Number of choices.\n * @returns A zero vote with the given number of choices.\n */\nexport const getZeroVote = (numChoices: number): number[] => {\n return Array(numChoices).fill(0)\n}\n\n/**\n * Decode bytes to bigint array (little-endian, 8 bytes per value).\n * @param data The bytes to decode (must be multiple of 8).\n * @returns Array of numbers.\n */\nexport const decodeBytesToNumbers = (data: Uint8Array): number[] => {\n if (data.length % 8 !== 0) {\n throw new Error('Data length must be multiple of 8')\n }\n\n const view = new DataView(data.buffer, data.byteOffset, data.byteLength)\n const arrayLength = data.length / 8\n const result: bigint[] = []\n\n for (let i = 0; i < arrayLength; i++) {\n result.push(view.getBigUint64(i * 8, true)) // true = little-endian\n }\n\n return result.map(Number)\n}\n\nexport const bigInt64ArrayToNumberArray = (bigInt64Array: BigInt64Array): number[] => {\n return Array.from(bigInt64Array).map(Number)\n}\n\nexport const numberArrayToBigInt64Array = (numberArray: number[]): BigInt64Array => {\n return BigInt64Array.from(numberArray.map(BigInt))\n}\n\n// Helper function to convert proof bytes to field elements\nexport const proofToFields = (proof: Uint8Array): string[] => {\n const fields: string[] = []\n for (let i = 0; i < proof.length; i += 32) {\n const chunk = proof.slice(i, i + 32)\n fields.push('0x' + Buffer.from(chunk).toString('hex'))\n }\n return fields\n}\n","// SPDX-License-Identifier: LGPL-3.0-only\n//\n// This file is provided WITHOUT ANY WARRANTY;\n// without even the implied warranty of MERCHANTABILITY\n// or FITNESS FOR A PARTICULAR PURPOSE.\n\nimport { hashMessage } from 'viem'\n\nexport const CRISP_SERVER_TOKEN_TREE_ENDPOINT = 'state/token-holders'\nexport const CRISP_SERVER_STATE_LITE_ENDPOINT = 'state/lite'\nexport const CRISP_SERVER_PREVIOUS_CIPHERTEXT_ENDPOINT = 'state/previous-ciphertext'\n\nexport const MERKLE_TREE_MAX_DEPTH = 20 // static, hardcoded in the circuit.\n\n// @note that the following must be changed accordingly to the CRISP circuit\n// Hard limit on the maximum number of vote bits supported for each option.\nexport const MAX_VOTE_BITS = 50\n// Hard limit on the maximum number of vote options supported.\nexport const MAX_VOTE_OPTIONS = 10\n\n/**\n * Message used by users to prove ownership of their Ethereum account\n * This message is signed by the user's private key to authenticate their identity\n * @notice Apps ideally want to use a different message to avoid signature reuse across different applications\n */\nexport const SIGNATURE_MESSAGE = 'CRISP: Sign this message to prove ownership of your Ethereum account'\nexport const SIGNATURE_MESSAGE_HASH = hashMessage(SIGNATURE_MESSAGE)\n\n// Placeholder signature for masking votes.\nexport const MASK_SIGNATURE =\n '0x8e7d77112641d59e9409ec3052041703bb9d9e6ed39bfcf75aefbcafe829ac6b21dd7648116ad5db0466fcb4bd468dcb28f6c069def8bc47cd9d859c85a016e31b'\n","// SPDX-License-Identifier: LGPL-3.0-only\n//\n// This file is provided WITHOUT ANY WARRANTY;\n// without even the implied warranty of MERCHANTABILITY\n// or FITNESS FOR A PARTICULAR PURPOSE.\n\nimport { getZkInputsGenerator, encodeVote, encryptVote } from './encoding'\nimport { extractSignatureComponents, getZeroVote, numberArrayToBigInt64Array } from './utils'\nimport type { ProofInputs } from './types'\n\n/**\n * Generate the circuit inputs for a vote proof.\n * Kept in a separate module so it can run in a worker.\n */\nexport const generateCircuitInputsImpl = async (proofInputs: ProofInputs): Promise<{ circuitInputs: any; encryptedVote: Uint8Array }> => {\n const zkInputsGenerator = getZkInputsGenerator()\n\n const numOptions = proofInputs.vote.length\n const zeroVote = getZeroVote(numOptions)\n const encodedVote = encodeVote(proofInputs.vote)\n\n let circuitInputs: any\n let encryptedVote: Uint8Array\n\n if (!proofInputs.previousCiphertext) {\n const result = await zkInputsGenerator.generateInputs(\n encryptVote(zeroVote, proofInputs.publicKey),\n proofInputs.publicKey,\n numberArrayToBigInt64Array(encodedVote),\n )\n\n circuitInputs = result.inputs\n encryptedVote = result.encryptedVote\n } else {\n const result = await zkInputsGenerator.generateInputsForUpdate(\n proofInputs.previousCiphertext,\n proofInputs.publicKey,\n numberArrayToBigInt64Array(encodedVote),\n )\n\n circuitInputs = result.inputs\n encryptedVote = result.encryptedVote\n }\n\n const signature = await extractSignatureComponents(proofInputs.signature, proofInputs.messageHash)\n\n circuitInputs.hashed_message = Array.from(signature.messageHash).map((b) => b.toString())\n circuitInputs.public_key_x = Array.from(signature.publicKeyX).map((b) => b.toString())\n circuitInputs.public_key_y = Array.from(signature.publicKeyY).map((b) => b.toString())\n circuitInputs.signature = Array.from(signature.signature).map((b) => b.toString())\n circuitInputs.slot_address = proofInputs.slotAddress.toLowerCase()\n circuitInputs.balance = proofInputs.balance.toString()\n circuitInputs.is_first_vote = !proofInputs.previousCiphertext\n circuitInputs.is_mask_vote = proofInputs.isMaskVote\n circuitInputs.merkle_root = proofInputs.merkleProof.proof.root.toString()\n circuitInputs.merkle_proof_length = proofInputs.merkleProof.length.toString()\n circuitInputs.merkle_proof_indices = proofInputs.merkleProof.indices.map((i) => i.toString())\n circuitInputs.merkle_proof_siblings = proofInputs.merkleProof.proof.siblings.map((s) => s.toString())\n circuitInputs.num_options = numOptions.toString()\n\n return { circuitInputs, encryptedVote }\n}\n","// SPDX-License-Identifier: LGPL-3.0-only\n//\n// Runs generateCircuitInputs in a worker to avoid blocking the main thread\n// during CPU-heavy zk-inputs WASM (BFV encryption).\n\nimport type { ProofInputs } from '../types'\nimport { generateCircuitInputsImpl } from '../circuitInputs'\n\nself.onmessage = async (e: MessageEvent<ProofInputs>) => {\n try {\n const result = await generateCircuitInputsImpl(e.data)\n self.postMessage({ type: 'result' as const, ...result })\n } catch (err) {\n const error = err instanceof Error ? err.message : String(err)\n const stack = err instanceof Error ? err.stack : undefined\n self.postMessage({ type: 'error' as const, error, stack })\n }\n}\n"],"mappings":"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","names":["ZKInputsGenerator","hexToBytes","ZKInputsGenerator"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crisp-e3/sdk",
3
- "version": "0.5.12",
3
+ "version": "0.7.0",
4
4
  "type": "module",
5
5
  "author": {
6
6
  "name": "gnosisguild",
@@ -14,7 +14,8 @@
14
14
  "types": "./dist/index.d.ts",
15
15
  "import": "./dist/index.js",
16
16
  "default": "./dist/index.js"
17
- }
17
+ },
18
+ "./workers/generateCircuitInputs.worker": "./dist/workers/generateCircuitInputs.worker.js"
18
19
  },
19
20
  "main": "./dist/index.js",
20
21
  "module": "./dist/index.js",
@@ -34,17 +35,22 @@
34
35
  "vitest": "^1.6.1"
35
36
  },
36
37
  "dependencies": {
37
- "@aztec/bb.js": "3.0.0-nightly.20251104",
38
- "@noir-lang/noir_js": "1.0.0-beta.15",
38
+ "@aztec/bb.js": "3.0.0-nightly.20260102",
39
+ "@noir-lang/noir_js": "1.0.0-beta.16",
39
40
  "@zk-kit/lean-imt": "^2.2.4",
40
41
  "poseidon-lite": "^0.3.0",
41
42
  "viem": "2.30.6",
42
- "@crisp-e3/zk-inputs": "0.5.12"
43
+ "@crisp-e3/zk-inputs": "0.7.0"
43
44
  },
44
45
  "scripts": {
45
- "compile:circuit": "cd ../../circuits && nargo compile",
46
+ "compile:circuits": "pnpm compile:crisp && pnpm compile:user_data_encryption_ct0 && pnpm compile:user_data_encryption_ct1 && pnpm compile:user_data_encryption && pnpm compile:fold",
47
+ "compile:user_data_encryption_ct0": "cd ../../../../circuits/bin/threshold/user_data_encryption_ct0 && nargo compile",
48
+ "compile:user_data_encryption_ct1": "cd ../../../../circuits/bin/threshold/user_data_encryption_ct1 && nargo compile",
49
+ "compile:user_data_encryption": "cd ../../../../circuits/bin/recursive_aggregation/wrapper/threshold/user_data_encryption && nargo compile",
50
+ "compile:crisp": "cd ../../circuits/bin/crisp && nargo compile",
51
+ "compile:fold": "cd ../../circuits/bin/fold && nargo compile",
46
52
  "build:wasm": "pnpm -C ../crisp-zk-inputs build",
47
- "build": "pnpm build:wasm && pnpm compile:circuit && tsup",
53
+ "build": "pnpm build:wasm && pnpm compile:circuits && tsup",
48
54
  "test": "vitest --run"
49
55
  }
50
56
  }