@devtion/backend 0.0.0-5d170d3 → 0.0.0-7cfaa5d
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 +26 -0
- package/dist/src/functions/index.js +127 -153
- package/dist/src/functions/index.mjs +127 -153
- package/dist/types/functions/ceremony.d.ts.map +1 -1
- package/dist/types/functions/circuit.d.ts.map +1 -1
- package/dist/types/functions/storage.d.ts.map +1 -1
- package/dist/types/functions/timeout.d.ts.map +1 -1
- package/dist/types/functions/user.d.ts.map +1 -1
- package/dist/types/lib/errors.d.ts +1 -0
- package/dist/types/lib/errors.d.ts.map +1 -1
- package/dist/types/lib/utils.d.ts +1 -1
- package/dist/types/lib/utils.d.ts.map +1 -1
- package/dist/types/types/index.d.ts +1 -1
- package/dist/types/types/index.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/functions/ceremony.ts +8 -3
- package/src/functions/circuit.ts +117 -181
- package/src/functions/participant.ts +8 -8
- package/src/functions/storage.ts +5 -3
- package/src/functions/timeout.ts +4 -3
- package/src/functions/user.ts +31 -7
- package/src/lib/errors.ts +5 -0
- package/src/lib/utils.ts +3 -3
- package/src/types/index.ts +1 -1
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
vmBootstrapCommand,
|
|
19
19
|
vmDependenciesAndCacheArtifactsCommand,
|
|
20
20
|
vmBootstrapScriptFilename
|
|
21
|
-
} from "@
|
|
21
|
+
} from "@devtion/actions"
|
|
22
22
|
import { encode } from "html-entities"
|
|
23
23
|
import { SetupCeremonyData } from "../types/index"
|
|
24
24
|
import { COMMON_ERRORS, logAndThrowError, printLog, SPECIFIC_ERRORS } from "../lib/errors"
|
|
@@ -146,7 +146,7 @@ export const setupCeremony = functions
|
|
|
146
146
|
// Check if using the VM approach for contribution verification.
|
|
147
147
|
if (circuit.verification.cfOrVm === CircuitContributionVerificationMechanism.VM) {
|
|
148
148
|
// VM command to be run at the startup.
|
|
149
|
-
const startupCommand = vmBootstrapCommand(bucketName)
|
|
149
|
+
const startupCommand = vmBootstrapCommand(`${bucketName}/circuits/${circuit.name!}`)
|
|
150
150
|
|
|
151
151
|
// Get EC2 client.
|
|
152
152
|
const ec2Client = await createEC2Client()
|
|
@@ -165,7 +165,12 @@ export const setupCeremony = functions
|
|
|
165
165
|
printLog(`Check VM dependencies and cache artifacts commands ${vmCommands.join("\n")}`, LogLevel.DEBUG)
|
|
166
166
|
|
|
167
167
|
// Upload the post-startup commands script file.
|
|
168
|
-
|
|
168
|
+
printLog(`Uploading VM post-startup commands script file ${vmBootstrapScriptFilename}`, LogLevel.DEBUG)
|
|
169
|
+
await uploadFileToBucketNoFile(
|
|
170
|
+
bucketName,
|
|
171
|
+
`circuits/${circuit.name!}/${vmBootstrapScriptFilename}`,
|
|
172
|
+
vmCommands.join("\n")
|
|
173
|
+
)
|
|
169
174
|
|
|
170
175
|
// Compute the VM disk space requirement (in GB).
|
|
171
176
|
const vmDiskSize = computeDiskSizeForVM(circuit.zKeySizeInBytes!, circuit.metadata?.pot!)
|
package/src/functions/circuit.ts
CHANGED
|
@@ -37,7 +37,7 @@ import {
|
|
|
37
37
|
createCustomLoggerForFile,
|
|
38
38
|
retrieveCommandStatus,
|
|
39
39
|
stopEC2Instance
|
|
40
|
-
} from "@
|
|
40
|
+
} from "@devtion/actions"
|
|
41
41
|
import { zKey } from "snarkjs"
|
|
42
42
|
import { CommandInvocationStatus, SSMClient } from "@aws-sdk/client-ssm"
|
|
43
43
|
import { FinalizeCircuitData, VerifyContributionData } from "../types/index"
|
|
@@ -58,6 +58,7 @@ import {
|
|
|
58
58
|
uploadFileToBucket
|
|
59
59
|
} from "../lib/utils"
|
|
60
60
|
import { EC2Client } from "@aws-sdk/client-ec2"
|
|
61
|
+
import { HttpsError } from "firebase-functions/v2/https"
|
|
61
62
|
|
|
62
63
|
dotenv.config()
|
|
63
64
|
|
|
@@ -131,6 +132,7 @@ const coordinate = async (
|
|
|
131
132
|
|
|
132
133
|
newParticipantStatus = ParticipantStatus.CONTRIBUTING
|
|
133
134
|
newContributionStep = ParticipantContributionStep.DOWNLOADING
|
|
135
|
+
newCurrentContributorId = participant.id
|
|
134
136
|
}
|
|
135
137
|
// Scenario (B).
|
|
136
138
|
else if (participantIsNotCurrentContributor) {
|
|
@@ -213,113 +215,71 @@ const coordinate = async (
|
|
|
213
215
|
* Wait until the command has completed its execution inside the VM.
|
|
214
216
|
* @dev this method implements a custom interval to check 5 times after 1 minute if the command execution
|
|
215
217
|
* has been completed or not by calling the `retrieveCommandStatus` method.
|
|
216
|
-
* @param {any} resolve the promise.
|
|
217
|
-
* @param {any} reject the promise.
|
|
218
218
|
* @param {SSMClient} ssm the SSM client.
|
|
219
219
|
* @param {string} vmInstanceId the unique identifier of the VM instance.
|
|
220
220
|
* @param {string} commandId the unique identifier of the VM command.
|
|
221
221
|
* @returns <Promise<void>> true when the command execution succeed; otherwise false.
|
|
222
222
|
*/
|
|
223
|
-
const waitForVMCommandExecution = (
|
|
224
|
-
resolve
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
223
|
+
const waitForVMCommandExecution = (ssm: SSMClient, vmInstanceId: string, commandId: string): Promise<void> =>
|
|
224
|
+
new Promise((resolve, reject) => {
|
|
225
|
+
const poll = async () => {
|
|
226
|
+
try {
|
|
227
|
+
// Get command status.
|
|
228
|
+
const cmdStatus = await retrieveCommandStatus(ssm, vmInstanceId, commandId)
|
|
229
|
+
printLog(`Checking command ${commandId} status => ${cmdStatus}`, LogLevel.DEBUG)
|
|
230
|
+
|
|
231
|
+
let error: HttpsError | undefined
|
|
232
|
+
switch (cmdStatus) {
|
|
233
|
+
case CommandInvocationStatus.CANCELLING:
|
|
234
|
+
case CommandInvocationStatus.CANCELLED: {
|
|
235
|
+
error = SPECIFIC_ERRORS.SE_VM_CANCELLED_COMMAND_EXECUTION
|
|
236
|
+
break
|
|
237
|
+
}
|
|
238
|
+
case CommandInvocationStatus.DELAYED: {
|
|
239
|
+
error = SPECIFIC_ERRORS.SE_VM_DELAYED_COMMAND_EXECUTION
|
|
240
|
+
break
|
|
241
|
+
}
|
|
242
|
+
case CommandInvocationStatus.FAILED: {
|
|
243
|
+
error = SPECIFIC_ERRORS.SE_VM_FAILED_COMMAND_EXECUTION
|
|
244
|
+
break
|
|
245
|
+
}
|
|
246
|
+
case CommandInvocationStatus.TIMED_OUT: {
|
|
247
|
+
error = SPECIFIC_ERRORS.SE_VM_TIMEDOUT_COMMAND_EXECUTION
|
|
248
|
+
break
|
|
249
|
+
}
|
|
250
|
+
case CommandInvocationStatus.IN_PROGRESS:
|
|
251
|
+
case CommandInvocationStatus.PENDING: {
|
|
252
|
+
// wait a minute and poll again
|
|
253
|
+
setTimeout(poll, 60000)
|
|
254
|
+
return
|
|
255
|
+
}
|
|
256
|
+
case CommandInvocationStatus.SUCCESS: {
|
|
257
|
+
printLog(`Command ${commandId} successfully completed`, LogLevel.DEBUG)
|
|
258
|
+
|
|
259
|
+
// Resolve the promise.
|
|
260
|
+
resolve()
|
|
261
|
+
return
|
|
262
|
+
}
|
|
263
|
+
default: {
|
|
264
|
+
logAndThrowError(SPECIFIC_ERRORS.SE_VM_UNKNOWN_COMMAND_STATUS)
|
|
265
|
+
}
|
|
266
|
+
}
|
|
258
267
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
}
|
|
265
|
-
}, 60000) // 1 minute.
|
|
266
|
-
}
|
|
268
|
+
if (error) {
|
|
269
|
+
logAndThrowError(error)
|
|
270
|
+
}
|
|
271
|
+
} catch (error: any) {
|
|
272
|
+
printLog(`Invalid command ${commandId} execution`, LogLevel.DEBUG)
|
|
267
273
|
|
|
268
|
-
|
|
269
|
-
* Wait until the artifacts have been downloaded.
|
|
270
|
-
* @param {any} resolve the promise.
|
|
271
|
-
* @param {any} reject the promise.
|
|
272
|
-
* @param {string} potTempFilePath the tmp path to the locally downloaded pot file.
|
|
273
|
-
* @param {string} firstZkeyTempFilePath the tmp path to the locally downloaded first zkey file.
|
|
274
|
-
* @param {string} lastZkeyTempFilePath the tmp path to the locally downloaded last zkey file.
|
|
275
|
-
*/
|
|
276
|
-
const waitForFileDownload = (
|
|
277
|
-
resolve: any,
|
|
278
|
-
reject: any,
|
|
279
|
-
potTempFilePath: string,
|
|
280
|
-
firstZkeyTempFilePath: string,
|
|
281
|
-
lastZkeyTempFilePath: string,
|
|
282
|
-
circuitId: string,
|
|
283
|
-
participantId: string
|
|
284
|
-
) => {
|
|
285
|
-
const maxWaitTime = 5 * 60 * 1000 // 5 minutes
|
|
286
|
-
// every second check if the file download was completed
|
|
287
|
-
const interval = setInterval(async () => {
|
|
288
|
-
printLog(`Verifying that the artifacts were downloaded for circuit ${circuitId} and participant ${participantId}`, LogLevel.DEBUG)
|
|
289
|
-
try {
|
|
290
|
-
// check if files have been downloaded
|
|
291
|
-
if (!fs.existsSync(potTempFilePath)) {
|
|
292
|
-
printLog(`Pot file not found at ${potTempFilePath}`, LogLevel.DEBUG)
|
|
293
|
-
}
|
|
294
|
-
if (!fs.existsSync(firstZkeyTempFilePath)) {
|
|
295
|
-
printLog(`First zkey file not found at ${firstZkeyTempFilePath}`, LogLevel.DEBUG)
|
|
296
|
-
}
|
|
297
|
-
if (!fs.existsSync(lastZkeyTempFilePath)) {
|
|
298
|
-
printLog(`Last zkey file not found at ${lastZkeyTempFilePath}`, LogLevel.DEBUG)
|
|
299
|
-
}
|
|
274
|
+
if (!error.toString().includes(commandId)) logAndThrowError(COMMON_ERRORS.CM_INVALID_COMMAND_EXECUTION)
|
|
300
275
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
printLog(`All required files are present on disk.`, LogLevel.INFO)
|
|
304
|
-
// resolve the promise
|
|
305
|
-
resolve()
|
|
276
|
+
// Reject the promise.
|
|
277
|
+
reject()
|
|
306
278
|
}
|
|
307
|
-
} catch (error: any) {
|
|
308
|
-
// if we have an error then we print it as a warning and reject
|
|
309
|
-
printLog(`Error while downloading files: ${error}`, LogLevel.WARN)
|
|
310
|
-
reject()
|
|
311
|
-
} finally {
|
|
312
|
-
printLog(`Clearing the interval for file download. Circuit ${circuitId} and participant ${participantId}`, LogLevel.DEBUG)
|
|
313
|
-
clearInterval(interval)
|
|
314
279
|
}
|
|
315
|
-
}, 5000)
|
|
316
280
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
clearInterval(interval)
|
|
320
|
-
reject(new Error('Timeout exceeded while waiting for files to be downloaded.'))
|
|
321
|
-
}, maxWaitTime)
|
|
322
|
-
}
|
|
281
|
+
setTimeout(poll, 60000)
|
|
282
|
+
})
|
|
323
283
|
|
|
324
284
|
/**
|
|
325
285
|
* This method is used to coordinate the waiting queues of ceremony circuits.
|
|
@@ -341,7 +301,7 @@ const waitForFileDownload = (
|
|
|
341
301
|
* - Just completed a contribution or all contributions for each circuit. If yes, coordinate (multi-participant scenario).
|
|
342
302
|
*/
|
|
343
303
|
export const coordinateCeremonyParticipant = functionsV1
|
|
344
|
-
.region(
|
|
304
|
+
.region("europe-west1")
|
|
345
305
|
.runWith({
|
|
346
306
|
memory: "512MB"
|
|
347
307
|
})
|
|
@@ -442,7 +402,6 @@ export const coordinateCeremonyParticipant = functionsV1
|
|
|
442
402
|
}
|
|
443
403
|
})
|
|
444
404
|
|
|
445
|
-
|
|
446
405
|
/**
|
|
447
406
|
* Recursive function to check whether an EC2 is in a running state
|
|
448
407
|
* @notice required step to run commands
|
|
@@ -451,16 +410,12 @@ export const coordinateCeremonyParticipant = functionsV1
|
|
|
451
410
|
* @param attempts <number> - how many times to retry before failing
|
|
452
411
|
* @returns <Promise<boolean>> - whether the VM was started
|
|
453
412
|
*/
|
|
454
|
-
const checkIfVMRunning = async (
|
|
455
|
-
ec2: EC2Client,
|
|
456
|
-
vmInstanceId: string,
|
|
457
|
-
attempts = 5
|
|
458
|
-
): Promise<boolean> => {
|
|
413
|
+
const checkIfVMRunning = async (ec2: EC2Client, vmInstanceId: string, attempts = 5): Promise<boolean> => {
|
|
459
414
|
// if we tried 5 times, then throw an error
|
|
460
415
|
if (attempts <= 0) logAndThrowError(SPECIFIC_ERRORS.SE_VM_NOT_RUNNING)
|
|
461
416
|
|
|
462
|
-
await sleep(60000)
|
|
463
|
-
const isVMRunning = await checkIfRunning(ec2, vmInstanceId)
|
|
417
|
+
await sleep(60000) // Wait for 1 min
|
|
418
|
+
const isVMRunning = await checkIfRunning(ec2, vmInstanceId)
|
|
464
419
|
|
|
465
420
|
if (!isVMRunning) {
|
|
466
421
|
printLog(`VM not running, ${attempts - 1} attempts remaining. Retrying in 1 minute...`, LogLevel.DEBUG)
|
|
@@ -497,7 +452,7 @@ const checkIfVMRunning = async (
|
|
|
497
452
|
* 2) Send all updates atomically to the Firestore database.
|
|
498
453
|
*/
|
|
499
454
|
export const verifycontribution = functionsV2.https.onCall(
|
|
500
|
-
{ memory: "16GiB", timeoutSeconds: 3600, region:
|
|
455
|
+
{ memory: "16GiB", timeoutSeconds: 3600, region: "europe-west1" },
|
|
501
456
|
async (request: functionsV2.https.CallableRequest<VerifyContributionData>): Promise<any> => {
|
|
502
457
|
if (!request.auth || (!request.auth.token.participant && !request.auth.token.coordinator))
|
|
503
458
|
logAndThrowError(SPECIFIC_ERRORS.SE_AUTH_NO_CURRENT_AUTH_USER)
|
|
@@ -665,9 +620,6 @@ export const verifycontribution = functionsV2.https.onCall(
|
|
|
665
620
|
verificationTranscriptTemporaryLocalPath,
|
|
666
621
|
true
|
|
667
622
|
)
|
|
668
|
-
|
|
669
|
-
// Stop VM instance.
|
|
670
|
-
await stopEC2Instance(ec2, vmInstanceId)
|
|
671
623
|
} else {
|
|
672
624
|
// Upload verification transcript.
|
|
673
625
|
/// nb. do not use multi-part upload here due to small file size.
|
|
@@ -744,6 +696,9 @@ export const verifycontribution = functionsV2.https.onCall(
|
|
|
744
696
|
})
|
|
745
697
|
}
|
|
746
698
|
|
|
699
|
+
// Stop VM instance
|
|
700
|
+
if (isUsingVM) await stopEC2Instance(ec2, vmInstanceId)
|
|
701
|
+
|
|
747
702
|
// Step (1.A.4.C)
|
|
748
703
|
if (!isFinalizing) {
|
|
749
704
|
// Step (1.A.4.C.1)
|
|
@@ -764,6 +719,8 @@ export const verifycontribution = functionsV2.https.onCall(
|
|
|
764
719
|
: verifyCloudFunctionTime
|
|
765
720
|
|
|
766
721
|
// Prepare tx to update circuit average contribution/verification time.
|
|
722
|
+
const updatedCircuitDoc = await getDocumentById(getCircuitsCollectionPath(ceremonyId), circuitId)
|
|
723
|
+
const { waitingQueue: updatedWaitingQueue } = updatedCircuitDoc.data()!
|
|
767
724
|
/// @dev this must happen only for valid contributions.
|
|
768
725
|
batch.update(circuitDoc.ref, {
|
|
769
726
|
avgTimings: {
|
|
@@ -776,7 +733,7 @@ export const verifycontribution = functionsV2.https.onCall(
|
|
|
776
733
|
: avgVerifyCloudFunctionTime
|
|
777
734
|
},
|
|
778
735
|
waitingQueue: {
|
|
779
|
-
...
|
|
736
|
+
...updatedWaitingQueue,
|
|
780
737
|
completedContributions: isContributionValid
|
|
781
738
|
? completedContributions + 1
|
|
782
739
|
: completedContributions,
|
|
@@ -835,9 +792,7 @@ export const verifycontribution = functionsV2.https.onCall(
|
|
|
835
792
|
printLog(`Starting the execution of command ${commandId}`, LogLevel.DEBUG)
|
|
836
793
|
|
|
837
794
|
// Step (1.A.3.3).
|
|
838
|
-
return
|
|
839
|
-
waitForVMCommandExecution(resolve, reject, ssm, vmInstanceId, commandId)
|
|
840
|
-
)
|
|
795
|
+
return waitForVMCommandExecution(ssm, vmInstanceId, commandId)
|
|
841
796
|
.then(async () => {
|
|
842
797
|
// Command execution successfully completed.
|
|
843
798
|
printLog(`Command ${commandId} execution has been successfully completed`, LogLevel.DEBUG)
|
|
@@ -849,76 +804,57 @@ export const verifycontribution = functionsV2.https.onCall(
|
|
|
849
804
|
|
|
850
805
|
logAndThrowError(COMMON_ERRORS.CM_INVALID_COMMAND_EXECUTION)
|
|
851
806
|
})
|
|
852
|
-
}
|
|
853
|
-
// CF approach.
|
|
854
|
-
printLog(`CF mechanism`, LogLevel.DEBUG)
|
|
855
|
-
|
|
856
|
-
const potStoragePath = getPotStorageFilePath(files.potFilename)
|
|
857
|
-
const firstZkeyStoragePath = getZkeyStorageFilePath(prefix, `${prefix}_${genesisZkeyIndex}.zkey`)
|
|
858
|
-
// Prepare temporary file paths.
|
|
859
|
-
// (nb. these are needed to download the necessary artifacts for verification from AWS S3).
|
|
860
|
-
verificationTranscriptTemporaryLocalPath = createTemporaryLocalPath(
|
|
861
|
-
verificationTranscriptCompleteFilename
|
|
862
|
-
)
|
|
863
|
-
const potTempFilePath = createTemporaryLocalPath(`${circuitId}_${participantDoc.id}.pot`)
|
|
864
|
-
const firstZkeyTempFilePath = createTemporaryLocalPath(`${circuitId}_${participantDoc.id}_genesis.zkey`)
|
|
865
|
-
const lastZkeyTempFilePath = createTemporaryLocalPath(`${circuitId}_${participantDoc.id}_last.zkey`)
|
|
866
|
-
|
|
867
|
-
// Create and populate transcript.
|
|
868
|
-
const transcriptLogger = createCustomLoggerForFile(verificationTranscriptTemporaryLocalPath)
|
|
869
|
-
transcriptLogger.info(
|
|
870
|
-
`${
|
|
871
|
-
isFinalizing ? `Final verification` : `Verification`
|
|
872
|
-
} transcript for ${prefix} circuit Phase 2 contribution.\n${
|
|
873
|
-
isFinalizing ? `Coordinator ` : `Contributor # ${Number(lastZkeyIndex)}`
|
|
874
|
-
} (${contributorOrCoordinatorIdentifier})\n`
|
|
875
|
-
)
|
|
876
|
-
|
|
877
|
-
// Step (1.A.2).
|
|
878
|
-
await downloadArtifactFromS3Bucket(bucketName, potStoragePath, potTempFilePath)
|
|
879
|
-
await downloadArtifactFromS3Bucket(bucketName, firstZkeyStoragePath, firstZkeyTempFilePath)
|
|
880
|
-
await downloadArtifactFromS3Bucket(bucketName, lastZkeyStoragePath, lastZkeyTempFilePath)
|
|
807
|
+
}
|
|
881
808
|
|
|
882
|
-
|
|
809
|
+
// CF approach.
|
|
810
|
+
printLog(`CF mechanism`, LogLevel.DEBUG)
|
|
811
|
+
|
|
812
|
+
const potStoragePath = getPotStorageFilePath(files.potFilename)
|
|
813
|
+
const firstZkeyStoragePath = getZkeyStorageFilePath(prefix, `${prefix}_${genesisZkeyIndex}.zkey`)
|
|
814
|
+
// Prepare temporary file paths.
|
|
815
|
+
// (nb. these are needed to download the necessary artifacts for verification from AWS S3).
|
|
816
|
+
verificationTranscriptTemporaryLocalPath = createTemporaryLocalPath(verificationTranscriptCompleteFilename)
|
|
817
|
+
const potTempFilePath = createTemporaryLocalPath(`${circuitId}_${participantDoc.id}.pot`)
|
|
818
|
+
const firstZkeyTempFilePath = createTemporaryLocalPath(`${circuitId}_${participantDoc.id}_genesis.zkey`)
|
|
819
|
+
const lastZkeyTempFilePath = createTemporaryLocalPath(`${circuitId}_${participantDoc.id}_last.zkey`)
|
|
820
|
+
|
|
821
|
+
// Create and populate transcript.
|
|
822
|
+
const transcriptLogger = createCustomLoggerForFile(verificationTranscriptTemporaryLocalPath)
|
|
823
|
+
transcriptLogger.info(
|
|
824
|
+
`${
|
|
825
|
+
isFinalizing ? `Final verification` : `Verification`
|
|
826
|
+
} transcript for ${prefix} circuit Phase 2 contribution.\n${
|
|
827
|
+
isFinalizing ? `Coordinator ` : `Contributor # ${Number(lastZkeyIndex)}`
|
|
828
|
+
} (${contributorOrCoordinatorIdentifier})\n`
|
|
829
|
+
)
|
|
883
830
|
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
.then(async () => {
|
|
889
|
-
printLog(`Downloads from AWS S3 bucket completed - ceremony ${ceremonyId} circuit ${circuitId}`, LogLevel.DEBUG)
|
|
890
|
-
|
|
891
|
-
// Step (1.A.4).
|
|
892
|
-
isContributionValid = await zKey.verifyFromInit(
|
|
893
|
-
firstZkeyTempFilePath,
|
|
894
|
-
potTempFilePath,
|
|
895
|
-
lastZkeyTempFilePath,
|
|
896
|
-
transcriptLogger
|
|
897
|
-
)
|
|
898
|
-
|
|
899
|
-
// Compute contribution hash.
|
|
900
|
-
lastZkeyBlake2bHash = await blake512FromPath(lastZkeyTempFilePath)
|
|
901
|
-
|
|
902
|
-
// Free resources by unlinking temporary folders.
|
|
903
|
-
// Do not free-up verification transcript path here.
|
|
904
|
-
try {
|
|
905
|
-
fs.unlinkSync(potTempFilePath)
|
|
906
|
-
fs.unlinkSync(firstZkeyTempFilePath)
|
|
907
|
-
fs.unlinkSync(lastZkeyTempFilePath)
|
|
908
|
-
} catch (error: any) {
|
|
909
|
-
printLog(`Error while unlinking temporary files - Error ${error}`, LogLevel.WARN)
|
|
910
|
-
}
|
|
831
|
+
// Step (1.A.2).
|
|
832
|
+
await downloadArtifactFromS3Bucket(bucketName, potStoragePath, potTempFilePath)
|
|
833
|
+
await downloadArtifactFromS3Bucket(bucketName, firstZkeyStoragePath, firstZkeyTempFilePath)
|
|
834
|
+
await downloadArtifactFromS3Bucket(bucketName, lastZkeyStoragePath, lastZkeyTempFilePath)
|
|
911
835
|
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
836
|
+
// Step (1.A.4).
|
|
837
|
+
isContributionValid = await zKey.verifyFromInit(
|
|
838
|
+
firstZkeyTempFilePath,
|
|
839
|
+
potTempFilePath,
|
|
840
|
+
lastZkeyTempFilePath,
|
|
841
|
+
transcriptLogger
|
|
842
|
+
)
|
|
918
843
|
|
|
919
|
-
|
|
920
|
-
|
|
844
|
+
// Compute contribution hash.
|
|
845
|
+
lastZkeyBlake2bHash = await blake512FromPath(lastZkeyTempFilePath)
|
|
846
|
+
|
|
847
|
+
// Free resources by unlinking temporary folders.
|
|
848
|
+
// Do not free-up verification transcript path here.
|
|
849
|
+
try {
|
|
850
|
+
fs.unlinkSync(potTempFilePath)
|
|
851
|
+
fs.unlinkSync(firstZkeyTempFilePath)
|
|
852
|
+
fs.unlinkSync(lastZkeyTempFilePath)
|
|
853
|
+
} catch (error: any) {
|
|
854
|
+
printLog(`Error while unlinking temporary files - Error ${error}`, LogLevel.WARN)
|
|
921
855
|
}
|
|
856
|
+
|
|
857
|
+
await completeVerification()
|
|
922
858
|
}
|
|
923
859
|
}
|
|
924
860
|
)
|
|
@@ -929,7 +865,7 @@ export const verifycontribution = functionsV2.https.onCall(
|
|
|
929
865
|
* this does not happen if the participant is actually the coordinator who is finalizing the ceremony.
|
|
930
866
|
*/
|
|
931
867
|
export const refreshParticipantAfterContributionVerification = functionsV1
|
|
932
|
-
.region(
|
|
868
|
+
.region("europe-west1")
|
|
933
869
|
.runWith({
|
|
934
870
|
memory: "512MB"
|
|
935
871
|
})
|
|
@@ -1012,7 +948,7 @@ export const refreshParticipantAfterContributionVerification = functionsV1
|
|
|
1012
948
|
* and verification key extracted from the circuit final contribution (as part of the ceremony finalization process).
|
|
1013
949
|
*/
|
|
1014
950
|
export const finalizeCircuit = functionsV1
|
|
1015
|
-
.region(
|
|
951
|
+
.region("europe-west1")
|
|
1016
952
|
.runWith({
|
|
1017
953
|
memory: "512MB"
|
|
1018
954
|
})
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
ParticipantContributionStep,
|
|
9
9
|
getParticipantsCollectionPath,
|
|
10
10
|
commonTerms
|
|
11
|
-
} from "@
|
|
11
|
+
} from "@devtion/actions"
|
|
12
12
|
import { FieldValue } from "firebase-admin/firestore"
|
|
13
13
|
import {
|
|
14
14
|
PermanentlyStoreCurrentContributionTimeAndHash,
|
|
@@ -44,7 +44,7 @@ dotenv.config()
|
|
|
44
44
|
* @dev true when the participant can participate (1.A, 3.B, 1.D); otherwise false.
|
|
45
45
|
*/
|
|
46
46
|
export const checkParticipantForCeremony = functions
|
|
47
|
-
.region(
|
|
47
|
+
.region("europe-west1")
|
|
48
48
|
.runWith({
|
|
49
49
|
memory: "512MB"
|
|
50
50
|
})
|
|
@@ -175,7 +175,7 @@ export const checkParticipantForCeremony = functions
|
|
|
175
175
|
* 2) the participant has just finished the contribution for a circuit (contributionProgress != 0 && status = CONTRIBUTED && contributionStep = COMPLETED).
|
|
176
176
|
*/
|
|
177
177
|
export const progressToNextCircuitForContribution = functions
|
|
178
|
-
.region(
|
|
178
|
+
.region("europe-west1")
|
|
179
179
|
.runWith({
|
|
180
180
|
memory: "512MB"
|
|
181
181
|
})
|
|
@@ -233,7 +233,7 @@ export const progressToNextCircuitForContribution = functions
|
|
|
233
233
|
* 5) Completed contribution computation and verification.
|
|
234
234
|
*/
|
|
235
235
|
export const progressToNextContributionStep = functions
|
|
236
|
-
.region(
|
|
236
|
+
.region("europe-west1")
|
|
237
237
|
.runWith({
|
|
238
238
|
memory: "512MB"
|
|
239
239
|
})
|
|
@@ -296,7 +296,7 @@ export const progressToNextContributionStep = functions
|
|
|
296
296
|
* @dev enable the current contributor to resume a contribution from where it had left off.
|
|
297
297
|
*/
|
|
298
298
|
export const permanentlyStoreCurrentContributionTimeAndHash = functions
|
|
299
|
-
.region(
|
|
299
|
+
.region("europe-west1")
|
|
300
300
|
.runWith({
|
|
301
301
|
memory: "512MB"
|
|
302
302
|
})
|
|
@@ -355,7 +355,7 @@ export const permanentlyStoreCurrentContributionTimeAndHash = functions
|
|
|
355
355
|
* @dev enable the current contributor to resume a multi-part upload from where it had left off.
|
|
356
356
|
*/
|
|
357
357
|
export const temporaryStoreCurrentContributionMultiPartUploadId = functions
|
|
358
|
-
.region(
|
|
358
|
+
.region("europe-west1")
|
|
359
359
|
.runWith({
|
|
360
360
|
memory: "512MB"
|
|
361
361
|
})
|
|
@@ -409,7 +409,7 @@ export const temporaryStoreCurrentContributionMultiPartUploadId = functions
|
|
|
409
409
|
* @dev enable the current contributor to resume a multi-part upload from where it had left off.
|
|
410
410
|
*/
|
|
411
411
|
export const temporaryStoreCurrentContributionUploadedChunkData = functions
|
|
412
|
-
.region(
|
|
412
|
+
.region("europe-west1")
|
|
413
413
|
.runWith({
|
|
414
414
|
memory: "512MB"
|
|
415
415
|
})
|
|
@@ -469,7 +469,7 @@ export const temporaryStoreCurrentContributionUploadedChunkData = functions
|
|
|
469
469
|
* contributed to every selected ceremony circuits (= DONE).
|
|
470
470
|
*/
|
|
471
471
|
export const checkAndPrepareCoordinatorForFinalization = functions
|
|
472
|
-
.region(
|
|
472
|
+
.region("europe-west1")
|
|
473
473
|
.runWith({
|
|
474
474
|
memory: "512MB"
|
|
475
475
|
})
|
package/src/functions/storage.ts
CHANGED
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
ParticipantContributionStep,
|
|
21
21
|
formatZkeyIndex,
|
|
22
22
|
getZkeyStorageFilePath
|
|
23
|
-
} from "@
|
|
23
|
+
} from "@devtion/actions"
|
|
24
24
|
import { getCeremonyCircuits, getDocumentById } from "../lib/utils"
|
|
25
25
|
import { COMMON_ERRORS, logAndThrowError, makeError, printLog, SPECIFIC_ERRORS } from "../lib/errors"
|
|
26
26
|
import { LogLevel } from "../types/enums"
|
|
@@ -193,8 +193,10 @@ export const createBucket = functions
|
|
|
193
193
|
CORSConfiguration: {
|
|
194
194
|
CORSRules: [
|
|
195
195
|
{
|
|
196
|
-
AllowedMethods: ["GET"],
|
|
197
|
-
AllowedOrigins: ["*"]
|
|
196
|
+
AllowedMethods: ["GET", "PUT"],
|
|
197
|
+
AllowedOrigins: ["*"],
|
|
198
|
+
ExposeHeaders: ["ETag", "Content-Length"],
|
|
199
|
+
AllowedHeaders: ["*"]
|
|
198
200
|
}
|
|
199
201
|
]
|
|
200
202
|
}
|
package/src/functions/timeout.ts
CHANGED
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
ParticipantStatus,
|
|
10
10
|
getTimeoutsCollectionPath,
|
|
11
11
|
commonTerms
|
|
12
|
-
} from "@
|
|
12
|
+
} from "@devtion/actions"
|
|
13
13
|
import {
|
|
14
14
|
getCeremonyCircuits,
|
|
15
15
|
getCurrentServerTimestampInMillis,
|
|
@@ -174,7 +174,7 @@ export const checkAndRemoveBlockingContributor = functions
|
|
|
174
174
|
const batch = firestore.batch()
|
|
175
175
|
|
|
176
176
|
// Remove current contributor from waiting queue.
|
|
177
|
-
contributors.shift(
|
|
177
|
+
contributors.shift()
|
|
178
178
|
|
|
179
179
|
// Check if someone else is ready to start the contribution.
|
|
180
180
|
if (contributors.length > 0) {
|
|
@@ -281,7 +281,8 @@ export const resumeContributionAfterTimeoutExpiration = functions
|
|
|
281
281
|
if (status === ParticipantStatus.EXHUMED)
|
|
282
282
|
await participantDoc.ref.update({
|
|
283
283
|
status: ParticipantStatus.READY,
|
|
284
|
-
lastUpdated: getCurrentServerTimestampInMillis()
|
|
284
|
+
lastUpdated: getCurrentServerTimestampInMillis(),
|
|
285
|
+
tempContributionData: {}
|
|
285
286
|
})
|
|
286
287
|
else logAndThrowError(SPECIFIC_ERRORS.SE_CONTRIBUTE_CANNOT_PROGRESS_TO_NEXT_CIRCUIT)
|
|
287
288
|
|