@devtion/actions 0.0.0-7e983e3

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.
Files changed (55) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +83 -0
  3. package/dist/index.mjs +2608 -0
  4. package/dist/index.node.js +2714 -0
  5. package/dist/types/hardhat.config.d.ts +6 -0
  6. package/dist/types/hardhat.config.d.ts.map +1 -0
  7. package/dist/types/src/helpers/authentication.d.ts +21 -0
  8. package/dist/types/src/helpers/authentication.d.ts.map +1 -0
  9. package/dist/types/src/helpers/constants.d.ts +194 -0
  10. package/dist/types/src/helpers/constants.d.ts.map +1 -0
  11. package/dist/types/src/helpers/contracts.d.ts +57 -0
  12. package/dist/types/src/helpers/contracts.d.ts.map +1 -0
  13. package/dist/types/src/helpers/crypto.d.ts +27 -0
  14. package/dist/types/src/helpers/crypto.d.ts.map +1 -0
  15. package/dist/types/src/helpers/database.d.ts +105 -0
  16. package/dist/types/src/helpers/database.d.ts.map +1 -0
  17. package/dist/types/src/helpers/functions.d.ts +145 -0
  18. package/dist/types/src/helpers/functions.d.ts.map +1 -0
  19. package/dist/types/src/helpers/security.d.ts +10 -0
  20. package/dist/types/src/helpers/security.d.ts.map +1 -0
  21. package/dist/types/src/helpers/services.d.ts +38 -0
  22. package/dist/types/src/helpers/services.d.ts.map +1 -0
  23. package/dist/types/src/helpers/storage.d.ts +121 -0
  24. package/dist/types/src/helpers/storage.d.ts.map +1 -0
  25. package/dist/types/src/helpers/tasks.d.ts +2 -0
  26. package/dist/types/src/helpers/tasks.d.ts.map +1 -0
  27. package/dist/types/src/helpers/utils.d.ts +139 -0
  28. package/dist/types/src/helpers/utils.d.ts.map +1 -0
  29. package/dist/types/src/helpers/verification.d.ts +95 -0
  30. package/dist/types/src/helpers/verification.d.ts.map +1 -0
  31. package/dist/types/src/helpers/vm.d.ts +112 -0
  32. package/dist/types/src/helpers/vm.d.ts.map +1 -0
  33. package/dist/types/src/index.d.ts +15 -0
  34. package/dist/types/src/index.d.ts.map +1 -0
  35. package/dist/types/src/types/enums.d.ts +133 -0
  36. package/dist/types/src/types/enums.d.ts.map +1 -0
  37. package/dist/types/src/types/index.d.ts +603 -0
  38. package/dist/types/src/types/index.d.ts.map +1 -0
  39. package/package.json +87 -0
  40. package/src/helpers/authentication.ts +37 -0
  41. package/src/helpers/constants.ts +312 -0
  42. package/src/helpers/contracts.ts +268 -0
  43. package/src/helpers/crypto.ts +55 -0
  44. package/src/helpers/database.ts +221 -0
  45. package/src/helpers/functions.ts +438 -0
  46. package/src/helpers/security.ts +86 -0
  47. package/src/helpers/services.ts +83 -0
  48. package/src/helpers/storage.ts +329 -0
  49. package/src/helpers/tasks.ts +56 -0
  50. package/src/helpers/utils.ts +743 -0
  51. package/src/helpers/verification.ts +354 -0
  52. package/src/helpers/vm.ts +392 -0
  53. package/src/index.ts +162 -0
  54. package/src/types/enums.ts +141 -0
  55. package/src/types/index.ts +650 -0
@@ -0,0 +1,354 @@
1
+ import { groth16, zKey } from "snarkjs"
2
+ import fs from "fs"
3
+ import { Firestore, where } from "firebase/firestore"
4
+ import { Functions } from "firebase/functions"
5
+ import {
6
+ numExpIterations,
7
+ commonTerms,
8
+ finalContributionIndex,
9
+ verifierSmartContractAcronym,
10
+ verificationKeyAcronym,
11
+ solidityVersion
12
+ } from "./constants"
13
+ import { compareHashes } from "./crypto"
14
+ import {
15
+ downloadCeremonyArtifact,
16
+ getBucketName,
17
+ getVerificationKeyStorageFilePath,
18
+ getVerifierContractStorageFilePath,
19
+ getWasmStorageFilePath,
20
+ getZkeyStorageFilePath
21
+ } from "./storage"
22
+ import {
23
+ fromQueryToFirebaseDocumentInfo,
24
+ getCeremonyCircuits,
25
+ getCircuitContributionsFromContributor,
26
+ queryCollection
27
+ } from "./database"
28
+ import { formatZkeyIndex } from "./utils"
29
+ import { CeremonyArtifacts } from "../types/index"
30
+
31
+ /**
32
+ * Verify that a zKey is valid
33
+ * @param r1csLocalFilePath <string> path to the r1cs file
34
+ * @param zkeyLocalPath <string> path to the zKey file
35
+ * @param potLocalFilePath <string> path to the PoT file
36
+ * @param logger <any> logger instance
37
+ * @returns <boolean> true if the zKey is valid, false otherwise
38
+ */
39
+ export const verifyZKey = async (
40
+ r1csLocalFilePath: string,
41
+ zkeyLocalPath: string,
42
+ potLocalFilePath: string,
43
+ logger?: any
44
+ ): Promise<boolean> => {
45
+ if (!fs.existsSync(r1csLocalFilePath)) throw new Error(`R1CS file not found at ${r1csLocalFilePath}`)
46
+
47
+ if (!fs.existsSync(zkeyLocalPath)) throw new Error(`zKey file not found at ${zkeyLocalPath}`)
48
+
49
+ if (!fs.existsSync(potLocalFilePath)) throw new Error(`PoT file not found at ${potLocalFilePath}`)
50
+
51
+ const res = await zKey.verifyFromR1cs(r1csLocalFilePath, potLocalFilePath, zkeyLocalPath, logger)
52
+ return res
53
+ }
54
+
55
+ /**
56
+ * Generates a GROTH16 proof
57
+ * @param circuitInput <object> Input to the circuit
58
+ * @param zkeyFilePath <string> Path to the proving key
59
+ * @param wasmFilePath <string> Path to the compiled circuit
60
+ * @param logger <any> Optional logger
61
+ * @returns <Promise<object>> The proof
62
+ */
63
+ export const generateGROTH16Proof = async (
64
+ circuitInput: object,
65
+ zkeyFilePath: string,
66
+ wasmFilePath: string,
67
+ logger?: any
68
+ ): Promise<any> => {
69
+ try {
70
+ const { proof, publicSignals } = await groth16.fullProve(circuitInput, wasmFilePath, zkeyFilePath, logger)
71
+ return {
72
+ proof,
73
+ publicSignals
74
+ }
75
+ } catch (error: any) {
76
+ throw new Error(
77
+ "There was an error while generating a proof. Please check that the input is correct, as well as the required system paths; and please try again."
78
+ )
79
+ }
80
+ }
81
+
82
+ /**
83
+ * Verifies a GROTH16 proof
84
+ * @param verificationKeyPath <string> Path to the verification key
85
+ * @param publicSignals <object> Public signals
86
+ * @param proof <object> Proof
87
+ * @returns <Promise<boolean>> Whether the proof is valid or not
88
+ */
89
+ export const verifyGROTH16Proof = async (
90
+ verificationKeyPath: string,
91
+ publicSignals: object,
92
+ proof: object
93
+ ): Promise<boolean> => {
94
+ const verificationKey = JSON.parse(fs.readFileSync(verificationKeyPath).toString())
95
+ const success = await groth16.verify(verificationKey, publicSignals, proof)
96
+ return success
97
+ }
98
+
99
+ /**
100
+ * Helper method to extract the Solidity verifier
101
+ * from a final zKey file and save it to a local file.
102
+ * @param finalZkeyPath <string> The path to the zKey file.
103
+ * @return <any> The Solidity verifier code.
104
+ */
105
+ export const exportVerifierContract = async (finalZkeyPath: string, templatePath: string) => {
106
+ // Extract verifier.
107
+ let verifierCode = await zKey.exportSolidityVerifier(
108
+ finalZkeyPath,
109
+ {
110
+ groth16: fs.readFileSync(templatePath).toString()
111
+ },
112
+ console
113
+ )
114
+
115
+ // Update solidity version.
116
+ verifierCode = verifierCode.replace(/pragma solidity \^\d+\.\d+\.\d+/, `pragma solidity ^${solidityVersion}`)
117
+
118
+ return verifierCode
119
+ }
120
+
121
+ /**
122
+ * Helpers method to extract the vKey from a final zKey file
123
+ * @param finalZkeyPath <string> The path to the zKey file.
124
+ * @return <any> The vKey.
125
+ */
126
+ export const exportVkey = async (finalZkeyPath: string) => {
127
+ const verificationKeyJSONData = await zKey.exportVerificationKey(finalZkeyPath)
128
+ return verificationKeyJSONData
129
+ }
130
+
131
+ /**
132
+ * Helper method to extract the Solidity verifier and the Verification key
133
+ * from a final zKey file and save them to local files.
134
+ * @param finalZkeyPath <string> The path to the zKey file.
135
+ * @param verifierLocalPath <string> The path to the local file where the verifier will be saved.
136
+ * @param vKeyLocalPath <string> The path to the local file where the vKey will be saved.
137
+ * @param templatePath <string> The path to the template file.
138
+ */
139
+ export const exportVerifierAndVKey = async (
140
+ finalZkeyPath: string,
141
+ verifierLocalPath: string,
142
+ vKeyLocalPath: string,
143
+ templatePath: string
144
+ ) => {
145
+ const verifierCode = await exportVerifierContract(finalZkeyPath, templatePath)
146
+ fs.writeFileSync(verifierLocalPath, verifierCode)
147
+ const verificationKeyJSONData = await exportVkey(finalZkeyPath)
148
+ fs.writeFileSync(vKeyLocalPath, JSON.stringify(verificationKeyJSONData))
149
+ }
150
+
151
+ /**
152
+ * Generate a zKey from scratch (useful to compute either the genesis or final zKey)
153
+ * @param isFinalizing <boolean> Whether the ceremony is finalizing or not
154
+ * @param r1csLocalPath <string> The path to the local r1cs file
155
+ * @param potLocalPath <string> The path to the local pot file
156
+ * @param zkeyLocalPath <string> The path to save the generated zKey
157
+ * @param logger <any> The logger instance
158
+ * @param finalContributionZKeyLocalPath <string> The path to the local zkey file of the final contribution (only for final zKey)
159
+ * @param coordinatorIdentifier <string> The identifier of the coordinator (only for final zKey)
160
+ * @param beacon <string> The beacon value for the last contribution (only for final zKey)
161
+ */
162
+ export const generateZkeyFromScratch = async (
163
+ isFinalizing: boolean,
164
+ r1csLocalPath: string,
165
+ potLocalPath: string,
166
+ zkeyLocalPath: string,
167
+ logger: any,
168
+ finalContributionZKeyLocalPath?: string,
169
+ coordinatorIdentifier?: string,
170
+ beacon?: string
171
+ ) => {
172
+ if (!fs.existsSync(r1csLocalPath) || !fs.existsSync(potLocalPath))
173
+ throw new Error(
174
+ "There was an error while opening the local files. Please make sure that you provided the right paths and try again."
175
+ )
176
+
177
+ if (isFinalizing) {
178
+ if (!fs.existsSync(finalContributionZKeyLocalPath!))
179
+ throw new Error(
180
+ "There was an error while opening the last zKey generated by a contributor. Please make sure that you provided the right path and try again."
181
+ )
182
+ await zKey.beacon(
183
+ finalContributionZKeyLocalPath,
184
+ zkeyLocalPath,
185
+ coordinatorIdentifier,
186
+ beacon,
187
+ numExpIterations,
188
+ logger
189
+ )
190
+ } else await zKey.newZKey(r1csLocalPath, potLocalPath, zkeyLocalPath, logger)
191
+ }
192
+
193
+ /**
194
+ * Helper function used to compare two ceremony artifacts
195
+ * @param firebaseFunctions <Functions> Firebase functions object
196
+ * @param localPath1 <string> Local path to store the first artifact
197
+ * @param localPath2 <string> Local path to store the second artifact
198
+ * @param storagePath1 <string> Storage path to the first artifact
199
+ * @param storagePath2 <string> Storage path to the second artifact
200
+ * @param bucketName1 <string> Bucket name of the first artifact
201
+ * @param bucketName2 <string> Bucket name of the second artifact
202
+ * @param cleanup <boolean> Whether to delete the downloaded files or not
203
+ * @returns <Promise<boolean>> true if the hashes match, false otherwise
204
+ */
205
+ export const compareCeremonyArtifacts = async (
206
+ firebaseFunctions: Functions,
207
+ localPath1: string,
208
+ localPath2: string,
209
+ storagePath1: string,
210
+ storagePath2: string,
211
+ bucketName1: string,
212
+ bucketName2: string,
213
+ cleanup: boolean
214
+ ): Promise<boolean> => {
215
+ // 1. download files
216
+ await downloadCeremonyArtifact(firebaseFunctions, bucketName1, storagePath1, localPath1)
217
+ await downloadCeremonyArtifact(firebaseFunctions, bucketName2, storagePath2, localPath2)
218
+ // 2. compare hashes
219
+ const res = await compareHashes(localPath1, localPath2)
220
+ // 3. cleanup
221
+ if (cleanup) {
222
+ fs.unlinkSync(localPath1)
223
+ fs.unlinkSync(localPath2)
224
+ }
225
+ // 4. return result
226
+ return res
227
+ }
228
+
229
+ /**
230
+ * Given a ceremony prefix, download all the ceremony artifacts
231
+ * @param functions <Functions> firebase functions instance
232
+ * @param firestore <Firestore> firebase firestore instance
233
+ * @param ceremonyPrefix <string> ceremony prefix
234
+ * @param outputDirectory <string> output directory where to
235
+ * @returns <Promise<CeremonyArtifacts[]>> array of ceremony artifacts
236
+ */
237
+ export const downloadAllCeremonyArtifacts = async (
238
+ functions: Functions,
239
+ firestore: Firestore,
240
+ ceremonyPrefix: string,
241
+ outputDirectory: string
242
+ ): Promise<CeremonyArtifacts[]> => {
243
+ // mkdir if not exists
244
+ if (!fs.existsSync(outputDirectory)) {
245
+ fs.mkdirSync(outputDirectory)
246
+ }
247
+
248
+ if (!process.env.CONFIG_CEREMONY_BUCKET_POSTFIX)
249
+ throw new Error("CONFIG_CEREMONY_BUCKET_POSTFIX not set. Please review your env file and try again.")
250
+
251
+ const ceremonyArtifacts: CeremonyArtifacts[] = []
252
+
253
+ // find the ceremony given the prefix
254
+ const ceremonyQuery = await queryCollection(firestore, commonTerms.collections.ceremonies.name, [
255
+ where(commonTerms.collections.ceremonies.fields.prefix, "==", ceremonyPrefix)
256
+ ])
257
+ // get the data
258
+ const ceremonyData = fromQueryToFirebaseDocumentInfo(ceremonyQuery.docs)
259
+ if (ceremonyData.length === 0)
260
+ throw new Error("Ceremony not found. Please review your ceremony prefix and try again.")
261
+ const ceremony = ceremonyData.at(0)!
262
+ // reconstruct the bucket name
263
+ const bucketName = getBucketName(ceremonyPrefix, process.env.CONFIG_CEREMONY_BUCKET_POSTFIX!)
264
+
265
+ const circuits = await getCeremonyCircuits(firestore, ceremony.id)
266
+ if (circuits.length === 0)
267
+ throw new Error("No circuits found for this ceremony. Please review your ceremony prefix and try again.")
268
+
269
+ // for each circuit we have to download artifacts
270
+ for (const circuit of circuits) {
271
+ // make a directory for storing the circuit artifacts
272
+ const circuitDir = `${outputDirectory}/${ceremony.data.prefix}/${circuit.data.prefix}`
273
+ fs.mkdirSync(circuitDir, { recursive: true })
274
+
275
+ // get all required file names in storage and for local storage
276
+ const { potStoragePath } = circuit.data.files
277
+ const potLocalPath = `${circuitDir}/${circuit.data.files.potFilename}`
278
+ const { r1csStoragePath } = circuit.data.files
279
+ const r1csLocalPath = `${circuitDir}/${circuit.data.files.r1csFilename}`
280
+ const contributions = circuit.data.waitingQueue.completedContributions
281
+ const zkeyIndex = formatZkeyIndex(contributions)
282
+ const lastZKeyStoragePath = getZkeyStorageFilePath(
283
+ circuit.data.prefix,
284
+ `${circuit.data.prefix}_${zkeyIndex}.zkey`
285
+ )
286
+ const lastZKeyLocalPath = `${circuitDir}/${circuit.data.prefix}_${zkeyIndex}.zkey`
287
+ const finalZKeyName = `${circuit.data.prefix}_${finalContributionIndex}.zkey`
288
+ const finalZkeyStoragePath = getZkeyStorageFilePath(circuit.data.prefix, finalZKeyName)
289
+ const finalZKeyLocalPath = `${circuitDir}/${finalZKeyName}`
290
+
291
+ const verifierStoragePath = getVerifierContractStorageFilePath(
292
+ circuit.data.prefix,
293
+ `${verifierSmartContractAcronym}.sol`
294
+ )
295
+ const verifierLocalPath = `${circuitDir}/${circuit.data.prefix}_${verifierSmartContractAcronym}.sol`
296
+
297
+ const vKeyStoragePath = getVerificationKeyStorageFilePath(circuit.data.prefix, `${verificationKeyAcronym}.json`)
298
+ const vKeyLocalPath = `${circuitDir}/${circuit.data.prefix}_${verificationKeyAcronym}.json`
299
+
300
+ const wasmStoragePath = getWasmStorageFilePath(circuit.data.prefix, `${circuit.data.prefix}.wasm`)
301
+ const wasmLocalPath = `${circuitDir}/${circuit.data.prefix}.wasm`
302
+
303
+ // download everything
304
+ await downloadCeremonyArtifact(functions, bucketName, potStoragePath, potLocalPath)
305
+ await downloadCeremonyArtifact(functions, bucketName, r1csStoragePath, r1csLocalPath)
306
+ await downloadCeremonyArtifact(functions, bucketName, lastZKeyStoragePath, lastZKeyLocalPath)
307
+ await downloadCeremonyArtifact(functions, bucketName, finalZkeyStoragePath, finalZKeyLocalPath)
308
+ await downloadCeremonyArtifact(functions, bucketName, verifierStoragePath, verifierLocalPath)
309
+ await downloadCeremonyArtifact(functions, bucketName, vKeyStoragePath, vKeyLocalPath)
310
+ await downloadCeremonyArtifact(functions, bucketName, wasmStoragePath, wasmLocalPath)
311
+
312
+ ceremonyArtifacts.push({
313
+ circuitPrefix: circuit.data.prefix,
314
+ circuitId: circuit.id,
315
+ directoryRoot: circuitDir,
316
+ potLocalFilePath: potLocalPath,
317
+ r1csLocalFilePath: r1csLocalPath,
318
+ finalZkeyLocalFilePath: finalZKeyLocalPath,
319
+ lastZkeyLocalFilePath: lastZKeyLocalPath,
320
+ verifierLocalFilePath: verifierLocalPath,
321
+ verificationKeyLocalFilePath: vKeyLocalPath,
322
+ wasmLocalFilePath: wasmLocalPath
323
+ })
324
+ }
325
+
326
+ return ceremonyArtifacts
327
+ }
328
+
329
+ /**
330
+ * Fetch the final contribution beacon from Firestore
331
+ * @param firestore <Firestore> firebase firestore instance
332
+ * @param ceremonyId <string> ceremony id
333
+ * @param circuitId <string> circuit id
334
+ * @param participantId <string> participant id
335
+ * @returns <Promise<string>> final contribution beacon
336
+ */
337
+ export const getFinalContributionBeacon = async (
338
+ firestore: Firestore,
339
+ ceremonyId: string,
340
+ circuitId: string,
341
+ participantId: string
342
+ ): Promise<string> => {
343
+ const contributions = await getCircuitContributionsFromContributor(firestore, ceremonyId, circuitId, participantId)
344
+
345
+ const filtered = contributions
346
+ .filter((contributionDocument: any) => contributionDocument.data.zkeyIndex === finalContributionIndex)
347
+ .at(0)
348
+ if (!filtered)
349
+ throw new Error(
350
+ "Final contribution not found. Please check that you provided the correct input data and try again."
351
+ )
352
+
353
+ return filtered.data.beacon.value
354
+ }