@devtion/backend 0.0.0-004e6ad → 0.0.0-08cd76b

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 (39) hide show
  1. package/dist/src/functions/index.js +426 -392
  2. package/dist/src/functions/index.mjs +427 -393
  3. package/dist/{types → src/functions/types}/functions/bandada.d.ts.map +1 -1
  4. package/dist/{types → src/functions/types}/functions/ceremony.d.ts.map +1 -1
  5. package/dist/{types → src/functions/types}/functions/circuit.d.ts.map +1 -1
  6. package/dist/{types → src/functions/types}/functions/storage.d.ts.map +1 -1
  7. package/dist/{types → src/functions/types}/lib/errors.d.ts +1 -0
  8. package/dist/src/functions/types/lib/errors.d.ts.map +1 -0
  9. package/dist/{types → src/functions/types}/lib/services.d.ts.map +1 -1
  10. package/dist/src/functions/types/lib/utils.d.ts.map +1 -0
  11. package/package.json +6 -6
  12. package/src/functions/bandada.ts +96 -97
  13. package/src/functions/ceremony.ts +7 -3
  14. package/src/functions/circuit.ts +408 -377
  15. package/src/functions/storage.ts +1 -0
  16. package/src/functions/timeout.ts +9 -9
  17. package/src/lib/errors.ts +5 -0
  18. package/dist/types/lib/errors.d.ts.map +0 -1
  19. package/dist/types/lib/utils.d.ts.map +0 -1
  20. /package/dist/{types → src/functions/types}/functions/bandada.d.ts +0 -0
  21. /package/dist/{types → src/functions/types}/functions/ceremony.d.ts +0 -0
  22. /package/dist/{types → src/functions/types}/functions/circuit.d.ts +0 -0
  23. /package/dist/{types → src/functions/types}/functions/index.d.ts +0 -0
  24. /package/dist/{types → src/functions/types}/functions/index.d.ts.map +0 -0
  25. /package/dist/{types → src/functions/types}/functions/participant.d.ts +0 -0
  26. /package/dist/{types → src/functions/types}/functions/participant.d.ts.map +0 -0
  27. /package/dist/{types → src/functions/types}/functions/siwe.d.ts +0 -0
  28. /package/dist/{types → src/functions/types}/functions/siwe.d.ts.map +0 -0
  29. /package/dist/{types → src/functions/types}/functions/storage.d.ts +0 -0
  30. /package/dist/{types → src/functions/types}/functions/timeout.d.ts +0 -0
  31. /package/dist/{types → src/functions/types}/functions/timeout.d.ts.map +0 -0
  32. /package/dist/{types → src/functions/types}/functions/user.d.ts +0 -0
  33. /package/dist/{types → src/functions/types}/functions/user.d.ts.map +0 -0
  34. /package/dist/{types → src/functions/types}/lib/services.d.ts +0 -0
  35. /package/dist/{types → src/functions/types}/lib/utils.d.ts +0 -0
  36. /package/dist/{types → src/functions/types}/types/enums.d.ts +0 -0
  37. /package/dist/{types → src/functions/types}/types/enums.d.ts.map +0 -0
  38. /package/dist/{types → src/functions/types}/types/index.d.ts +0 -0
  39. /package/dist/{types → src/functions/types}/types/index.d.ts.map +0 -0
@@ -44,7 +44,7 @@ import { EC2Client } from "@aws-sdk/client-ec2"
44
44
  import { HttpsError } from "firebase-functions/v2/https"
45
45
  import { FinalizeCircuitData, VerifyContributionData } from "../types/index"
46
46
  import { LogLevel } from "../types/enums"
47
- import { COMMON_ERRORS, logAndThrowError, printLog, SPECIFIC_ERRORS } from "../lib/errors"
47
+ import { COMMON_ERRORS, logAndThrowError, makeError, printLog, SPECIFIC_ERRORS } from "../lib/errors"
48
48
  import {
49
49
  createEC2Client,
50
50
  createSSMClient,
@@ -115,7 +115,7 @@ const coordinate = async (
115
115
  if (isSingleParticipantCoordination) {
116
116
  // Scenario (A).
117
117
  if (emptyWaitingQueue) {
118
- printLog(`Coordinate - executing scenario A - emptyWaitingQueue`, LogLevel.DEBUG)
118
+ printLog(`Coordinate - executing scenario A - emptyWaitingQueue`, LogLevel.INFO)
119
119
 
120
120
  // Update.
121
121
  newCurrentContributorId = participant.id
@@ -127,7 +127,7 @@ const coordinate = async (
127
127
  else if (participantResumingAfterTimeoutExpiration) {
128
128
  printLog(
129
129
  `Coordinate - executing scenario A - single - participantResumingAfterTimeoutExpiration`,
130
- LogLevel.DEBUG
130
+ LogLevel.INFO
131
131
  )
132
132
 
133
133
  newParticipantStatus = ParticipantStatus.CONTRIBUTING
@@ -136,7 +136,7 @@ const coordinate = async (
136
136
  }
137
137
  // Scenario (B).
138
138
  else if (participantIsNotCurrentContributor) {
139
- printLog(`Coordinate - executing scenario B - single - participantIsNotCurrentContributor`, LogLevel.DEBUG)
139
+ printLog(`Coordinate - executing scenario B - single - participantIsNotCurrentContributor`, LogLevel.INFO)
140
140
 
141
141
  newCurrentContributorId = currentContributor
142
142
  newParticipantStatus = ParticipantStatus.WAITING
@@ -160,7 +160,7 @@ const coordinate = async (
160
160
  } else if (participantIsCurrentContributor && participantCompletedOneOrAllContributions && !!ceremonyId) {
161
161
  printLog(
162
162
  `Coordinate - executing scenario C - multi - participantIsCurrentContributor && participantCompletedOneOrAllContributions`,
163
- LogLevel.DEBUG
163
+ LogLevel.INFO
164
164
  )
165
165
 
166
166
  newParticipantStatus = ParticipantStatus.CONTRIBUTING
@@ -190,7 +190,7 @@ const coordinate = async (
190
190
 
191
191
  printLog(
192
192
  `Participant ${newCurrentContributorId} is the new current contributor for circuit ${circuit.id}`,
193
- LogLevel.DEBUG
193
+ LogLevel.INFO
194
194
  )
195
195
  }
196
196
  }
@@ -276,8 +276,8 @@ const waitForVMCommandExecution = (ssm: SSMClient, vmInstanceId: string, command
276
276
  // if it errors out, let's just log it as a warning so the coordinator is aware
277
277
  try {
278
278
  await stopEC2Instance(ec2, vmInstanceId)
279
- } catch (error: any) {
280
- printLog(`Error while stopping VM instance ${vmInstanceId} - Error ${error}`, LogLevel.WARN)
279
+ } catch (stopError: any) {
280
+ printLog(`Error while stopping VM instance ${vmInstanceId} - Error ${stopError}`, LogLevel.WARN)
281
281
  }
282
282
 
283
283
  if (!error.toString().includes(commandId)) logAndThrowError(COMMON_ERRORS.CM_INVALID_COMMAND_EXECUTION)
@@ -346,10 +346,10 @@ export const coordinateCeremonyParticipant = functionsV1
346
346
  contributionStep: changedContributionStep
347
347
  } = changedParticipant.data()!
348
348
 
349
- printLog(`Coordinate participant ${exParticipant.id} for ceremony ${ceremonyId}`, LogLevel.DEBUG)
349
+ printLog(`Coordinate participant ${exParticipant.id} for ceremony ${ceremonyId}`, LogLevel.INFO)
350
350
  printLog(
351
351
  `Participant status: ${prevStatus} => ${changedStatus} - Participant contribution step: ${prevContributionStep} => ${changedContributionStep}`,
352
- LogLevel.DEBUG
352
+ LogLevel.INFO
353
353
  )
354
354
 
355
355
  // Define pre-conditions.
@@ -370,8 +370,8 @@ export const coordinateCeremonyParticipant = functionsV1
370
370
 
371
371
  const participantCompletedContribution =
372
372
  prevContributionProgress === changedContributionProgress &&
373
- prevStatus === ParticipantStatus.CONTRIBUTING &&
374
- prevContributionStep === ParticipantContributionStep.VERIFYING &&
373
+ (prevStatus === ParticipantStatus.CONTRIBUTING ||
374
+ prevContributionStep === ParticipantContributionStep.VERIFYING) &&
375
375
  changedStatus === ParticipantStatus.CONTRIBUTED &&
376
376
  changedContributionStep === ParticipantContributionStep.COMPLETED
377
377
 
@@ -384,7 +384,7 @@ export const coordinateCeremonyParticipant = functionsV1
384
384
  // Step (2.A).
385
385
  printLog(
386
386
  `Participant is ready for first contribution (${participantReadyForFirstContribution}) or for the next contribution (${participantReadyForNextContribution}) or is resuming after a timeout expiration (${participantResumingContributionAfterTimeout})`,
387
- LogLevel.DEBUG
387
+ LogLevel.INFO
388
388
  )
389
389
 
390
390
  // Get the circuit.
@@ -398,7 +398,7 @@ export const coordinateCeremonyParticipant = functionsV1
398
398
  // Step (2.B).
399
399
  printLog(
400
400
  `Participant completed a contribution (${participantCompletedContribution}) or every contribution for each circuit (${participantCompletedEveryCircuitContribution})`,
401
- LogLevel.DEBUG
401
+ LogLevel.INFO
402
402
  )
403
403
 
404
404
  // Get the circuit.
@@ -460,417 +460,448 @@ const checkIfVMRunning = async (ec2: EC2Client, vmInstanceId: string, attempts =
460
460
  * 2) Send all updates atomically to the Firestore database.
461
461
  */
462
462
  export const verifycontribution = functionsV2.https.onCall(
463
- { memory: "16GiB", timeoutSeconds: 3600, region: "europe-west1" },
463
+ { memory: "32GiB", timeoutSeconds: 3600, region: "europe-west1", cpu: 8 },
464
464
  async (request: functionsV2.https.CallableRequest<VerifyContributionData>): Promise<any> => {
465
- if (!request.auth || (!request.auth.token.participant && !request.auth.token.coordinator))
466
- logAndThrowError(SPECIFIC_ERRORS.SE_AUTH_NO_CURRENT_AUTH_USER)
467
-
468
- if (
469
- !request.data.ceremonyId ||
470
- !request.data.circuitId ||
471
- !request.data.contributorOrCoordinatorIdentifier ||
472
- !request.data.bucketName
473
- )
474
- logAndThrowError(COMMON_ERRORS.CM_MISSING_OR_WRONG_INPUT_DATA)
475
-
476
- if (
477
- !process.env.CUSTOM_CONTRIBUTION_VERIFICATION_SOFTWARE_NAME ||
478
- !process.env.CUSTOM_CONTRIBUTION_VERIFICATION_SOFTWARE_VERSION ||
479
- !process.env.CUSTOM_CONTRIBUTION_VERIFICATION_SOFTWARE_COMMIT_HASH
480
- )
481
- logAndThrowError(COMMON_ERRORS.CM_WRONG_CONFIGURATION)
482
-
483
- // Step (0).
465
+ try {
466
+ if (!request.auth || (!request.auth.token.participant && !request.auth.token.coordinator))
467
+ logAndThrowError(SPECIFIC_ERRORS.SE_AUTH_NO_CURRENT_AUTH_USER)
468
+
469
+ if (
470
+ !request.data.ceremonyId ||
471
+ !request.data.circuitId ||
472
+ !request.data.contributorOrCoordinatorIdentifier ||
473
+ !request.data.bucketName
474
+ )
475
+ logAndThrowError(COMMON_ERRORS.CM_MISSING_OR_WRONG_INPUT_DATA)
484
476
 
485
- // Prepare and start timer.
486
- const verifyContributionTimer = new Timer({ label: commonTerms.cloudFunctionsNames.verifyContribution })
487
- verifyContributionTimer.start()
477
+ if (
478
+ !process.env.CUSTOM_CONTRIBUTION_VERIFICATION_SOFTWARE_NAME ||
479
+ !process.env.CUSTOM_CONTRIBUTION_VERIFICATION_SOFTWARE_VERSION ||
480
+ !process.env.CUSTOM_CONTRIBUTION_VERIFICATION_SOFTWARE_COMMIT_HASH
481
+ )
482
+ logAndThrowError(COMMON_ERRORS.CM_WRONG_CONFIGURATION)
483
+
484
+ const BUCKET_NAME_REGEX = /^[a-z0-9][a-z0-9-]{1,61}[a-z0-9]$/
485
+ if (!BUCKET_NAME_REGEX.test(request.data.bucketName)) logAndThrowError(SPECIFIC_ERRORS.WRONG_BUCKET_NAME)
486
+
487
+ // Step (0).
488
+
489
+ // Prepare and start timer.
490
+ const verifyContributionTimer = new Timer({ label: commonTerms.cloudFunctionsNames.verifyContribution })
491
+ verifyContributionTimer.start()
492
+
493
+ // Get DB.
494
+ const firestore = admin.firestore()
495
+ // Prepare batch of txs.
496
+ const batch = firestore.batch()
497
+
498
+ // Extract data.
499
+ const { ceremonyId, circuitId, contributorOrCoordinatorIdentifier, bucketName } = request.data
500
+ const userId = request.auth?.uid
501
+
502
+ // Look for the ceremony, circuit and participant document.
503
+ const ceremonyDoc = await getDocumentById(commonTerms.collections.ceremonies.name, ceremonyId)
504
+ const circuitDoc = await getDocumentById(getCircuitsCollectionPath(ceremonyId), circuitId)
505
+ const participantDoc = await getDocumentById(getParticipantsCollectionPath(ceremonyId), userId!)
506
+
507
+ if (!ceremonyDoc.data() || !circuitDoc.data() || !participantDoc.data())
508
+ logAndThrowError(COMMON_ERRORS.CM_INEXISTENT_DOCUMENT_DATA)
509
+
510
+ // Extract documents data.
511
+ const { state } = ceremonyDoc.data()!
512
+ const { status, contributions, verificationStartedAt, contributionStartedAt } = participantDoc.data()!
513
+ const { waitingQueue, prefix, avgTimings, verification, files } = circuitDoc.data()!
514
+ const { completedContributions, failedContributions } = waitingQueue
515
+ const {
516
+ contributionComputation: avgContributionComputationTime,
517
+ fullContribution: avgFullContributionTime,
518
+ verifyCloudFunction: avgVerifyCloudFunctionTime
519
+ } = avgTimings
520
+ const { cfOrVm, vm } = verification
521
+ // we might not have it if the circuit is not using VM.
522
+ let vmInstanceId: string = ""
523
+ if (vm) vmInstanceId = vm.vmInstanceId
488
524
 
489
- // Get DB.
490
- const firestore = admin.firestore()
491
- // Prepare batch of txs.
492
- const batch = firestore.batch()
525
+ // Define pre-conditions.
526
+ const isFinalizing = state === CeremonyState.CLOSED && request.auth && request.auth.token.coordinator // true only when the coordinator verifies the final contributions.
527
+ const isContributing = status === ParticipantStatus.CONTRIBUTING
528
+ const isUsingVM = cfOrVm === CircuitContributionVerificationMechanism.VM && !!vmInstanceId
529
+
530
+ // Prepare state.
531
+ let isContributionValid = false
532
+ let verifyCloudFunctionExecutionTime = 0 // time spent while executing the verify contribution cloud function.
533
+ let verifyCloudFunctionTime = 0 // time spent while executing the core business logic of this cloud function.
534
+ let fullContributionTime = 0 // time spent while doing non-verification contributions tasks (download, compute, upload).
535
+ let contributionComputationTime = 0 // time spent while computing the contribution.
536
+ let lastZkeyBlake2bHash: string = "" // the Blake2B hash of the last zKey.
537
+ let verificationTranscriptTemporaryLocalPath: string = "" // the local temporary path for the verification transcript.
538
+ let transcriptBlake2bHash: string = "" // the Blake2B hash of the verification transcript.
539
+ let commandId: string = "" // the unique identifier of the VM command.
540
+
541
+ // Derive necessary data.
542
+ const lastZkeyIndex = formatZkeyIndex(completedContributions + 1)
543
+ const verificationTranscriptCompleteFilename = `${prefix}_${
544
+ isFinalizing
545
+ ? `${contributorOrCoordinatorIdentifier}_${finalContributionIndex}_verification_transcript.log`
546
+ : `${lastZkeyIndex}_${contributorOrCoordinatorIdentifier}_verification_transcript.log`
547
+ }`
548
+
549
+ const lastZkeyFilename = `${prefix}_${isFinalizing ? finalContributionIndex : lastZkeyIndex}.zkey`
550
+
551
+ // Prepare state for VM verification (if needed).
552
+ const ec2 = await createEC2Client()
553
+ const ssm = await createSSMClient()
554
+
555
+ // Step (1.A.1).
556
+ // Get storage paths.
557
+ const verificationTranscriptStoragePathAndFilename = getTranscriptStorageFilePath(
558
+ prefix,
559
+ verificationTranscriptCompleteFilename
560
+ )
561
+ // the zKey storage path is required to be sent to the VM api
562
+ const lastZkeyStoragePath = getZkeyStorageFilePath(
563
+ prefix,
564
+ `${prefix}_${isFinalizing ? finalContributionIndex : lastZkeyIndex}.zkey`
565
+ )
493
566
 
494
- // Extract data.
495
- const { ceremonyId, circuitId, contributorOrCoordinatorIdentifier, bucketName } = request.data
496
- const userId = request.auth?.uid
567
+ const verificationTaskTimer = new Timer({ label: `${ceremonyId}-${circuitId}-${participantDoc.id}` })
497
568
 
498
- // Look for the ceremony, circuit and participant document.
499
- const ceremonyDoc = await getDocumentById(commonTerms.collections.ceremonies.name, ceremonyId)
500
- const circuitDoc = await getDocumentById(getCircuitsCollectionPath(ceremonyId), circuitId)
501
- const participantDoc = await getDocumentById(getParticipantsCollectionPath(ceremonyId), userId!)
569
+ const dumpLog = async (path: string): Promise<void> => {
570
+ printLog(`transcript >>>>>>`, LogLevel.DEBUG)
571
+ try {
572
+ const data = await fs.promises.readFile(path, "utf8")
573
+ printLog(data, LogLevel.DEBUG)
574
+ } catch (readError: any) {
575
+ printLog(readError, LogLevel.ERROR)
576
+ }
577
+ }
502
578
 
503
- if (!ceremonyDoc.data() || !circuitDoc.data() || !participantDoc.data())
504
- logAndThrowError(COMMON_ERRORS.CM_INEXISTENT_DOCUMENT_DATA)
579
+ const completeVerification = async () => {
580
+ // Stop verification task timer.
581
+ printLog("Completing verification", LogLevel.DEBUG)
582
+ verificationTaskTimer.stop()
583
+ verifyCloudFunctionExecutionTime = verificationTaskTimer.ms()
505
584
 
506
- // Extract documents data.
507
- const { state } = ceremonyDoc.data()!
508
- const { status, contributions, verificationStartedAt, contributionStartedAt } = participantDoc.data()!
509
- const { waitingQueue, prefix, avgTimings, verification, files } = circuitDoc.data()!
510
- const { completedContributions, failedContributions } = waitingQueue
511
- const {
512
- contributionComputation: avgContributionComputationTime,
513
- fullContribution: avgFullContributionTime,
514
- verifyCloudFunction: avgVerifyCloudFunctionTime
515
- } = avgTimings
516
- const { cfOrVm, vm } = verification
517
- // we might not have it if the circuit is not using VM.
518
- let vmInstanceId: string = ""
519
- if (vm) vmInstanceId = vm.vmInstanceId
585
+ if (isUsingVM) {
586
+ // Create temporary path.
587
+ verificationTranscriptTemporaryLocalPath = createTemporaryLocalPath(
588
+ `${circuitId}_${participantDoc.id}.log`
589
+ )
520
590
 
521
- // Define pre-conditions.
522
- const isFinalizing = state === CeremonyState.CLOSED && request.auth && request.auth.token.coordinator // true only when the coordinator verifies the final contributions.
523
- const isContributing = status === ParticipantStatus.CONTRIBUTING
524
- const isUsingVM = cfOrVm === CircuitContributionVerificationMechanism.VM && !!vmInstanceId
525
-
526
- // Prepare state.
527
- let isContributionValid = false
528
- let verifyCloudFunctionExecutionTime = 0 // time spent while executing the verify contribution cloud function.
529
- let verifyCloudFunctionTime = 0 // time spent while executing the core business logic of this cloud function.
530
- let fullContributionTime = 0 // time spent while doing non-verification contributions tasks (download, compute, upload).
531
- let contributionComputationTime = 0 // time spent while computing the contribution.
532
- let lastZkeyBlake2bHash: string = "" // the Blake2B hash of the last zKey.
533
- let verificationTranscriptTemporaryLocalPath: string = "" // the local temporary path for the verification transcript.
534
- let transcriptBlake2bHash: string = "" // the Blake2B hash of the verification transcript.
535
- let commandId: string = "" // the unique identifier of the VM command.
536
-
537
- // Derive necessary data.
538
- const lastZkeyIndex = formatZkeyIndex(completedContributions + 1)
539
- const verificationTranscriptCompleteFilename = `${prefix}_${
540
- isFinalizing
541
- ? `${contributorOrCoordinatorIdentifier}_${finalContributionIndex}_verification_transcript.log`
542
- : `${lastZkeyIndex}_${contributorOrCoordinatorIdentifier}_verification_transcript.log`
543
- }`
544
-
545
- const lastZkeyFilename = `${prefix}_${isFinalizing ? finalContributionIndex : lastZkeyIndex}.zkey`
546
-
547
- // Prepare state for VM verification (if needed).
548
- const ec2 = await createEC2Client()
549
- const ssm = await createSSMClient()
550
-
551
- // Step (1.A.1).
552
- // Get storage paths.
553
- const verificationTranscriptStoragePathAndFilename = getTranscriptStorageFilePath(
554
- prefix,
555
- verificationTranscriptCompleteFilename
556
- )
557
- // the zKey storage path is required to be sent to the VM api
558
- const lastZkeyStoragePath = getZkeyStorageFilePath(
559
- prefix,
560
- `${prefix}_${isFinalizing ? finalContributionIndex : lastZkeyIndex}.zkey`
561
- )
591
+ await sleep(1000) // wait 1s for file creation.
562
592
 
563
- const verificationTaskTimer = new Timer({ label: `${ceremonyId}-${circuitId}-${participantDoc.id}` })
593
+ // Download from bucket.
594
+ // nb. the transcript MUST be uploaded from the VM by verification commands.
595
+ await downloadArtifactFromS3Bucket(
596
+ bucketName,
597
+ verificationTranscriptStoragePathAndFilename,
598
+ verificationTranscriptTemporaryLocalPath
599
+ )
564
600
 
565
- const completeVerification = async () => {
566
- // Stop verification task timer.
567
- printLog("Completing verification", LogLevel.DEBUG)
568
- verificationTaskTimer.stop()
569
- verifyCloudFunctionExecutionTime = verificationTaskTimer.ms()
601
+ // Read the verification trascript and validate data by checking for core info ("ZKey Ok!").
602
+ const content = fs.readFileSync(verificationTranscriptTemporaryLocalPath, "utf-8")
570
603
 
571
- if (isUsingVM) {
572
- // Create temporary path.
573
- verificationTranscriptTemporaryLocalPath = createTemporaryLocalPath(
574
- `${circuitId}_${participantDoc.id}.log`
575
- )
604
+ if (content.includes("ZKey Ok!")) isContributionValid = true
576
605
 
577
- await sleep(1000) // wait 1s for file creation.
606
+ // If the contribution is valid, then format and store the trascript.
607
+ if (isContributionValid) {
608
+ // eslint-disable-next-line no-control-regex
609
+ const updated = content.replace(/\x1b[[0-9;]*m/g, "")
578
610
 
579
- // Download from bucket.
580
- // nb. the transcript MUST be uploaded from the VM by verification commands.
581
- await downloadArtifactFromS3Bucket(
582
- bucketName,
583
- verificationTranscriptStoragePathAndFilename,
584
- verificationTranscriptTemporaryLocalPath
585
- )
611
+ fs.writeFileSync(verificationTranscriptTemporaryLocalPath, updated)
612
+ }
613
+ }
586
614
 
587
- // Read the verification trascript and validate data by checking for core info ("ZKey Ok!").
588
- const content = fs.readFileSync(verificationTranscriptTemporaryLocalPath, "utf-8")
615
+ printLog(`The contribution has been verified - Result ${isContributionValid}`, LogLevel.DEBUG)
589
616
 
590
- if (content.includes("ZKey Ok!")) isContributionValid = true
617
+ // Create a new contribution document.
618
+ const contributionDoc = await firestore
619
+ .collection(getContributionsCollectionPath(ceremonyId, circuitId))
620
+ .doc()
621
+ .get()
591
622
 
592
- // If the contribution is valid, then format and store the trascript.
623
+ // Step (1.A.4).
593
624
  if (isContributionValid) {
594
- // eslint-disable-next-line no-control-regex
595
- const updated = content.replace(/\x1b[[0-9;]*m/g, "")
596
-
597
- fs.writeFileSync(verificationTranscriptTemporaryLocalPath, updated)
598
- }
599
- }
600
-
601
- printLog(`The contribution has been verified - Result ${isContributionValid}`, LogLevel.DEBUG)
602
-
603
- // Create a new contribution document.
604
- const contributionDoc = await firestore
605
- .collection(getContributionsCollectionPath(ceremonyId, circuitId))
606
- .doc()
607
- .get()
625
+ // Sleep ~3 seconds to wait for verification transcription.
626
+ await sleep(3000)
627
+
628
+ // Step (1.A.4.A.1).
629
+ if (isUsingVM) {
630
+ // Retrieve the contribution hash from the command output.
631
+ lastZkeyBlake2bHash = await retrieveCommandOutput(ssm, vmInstanceId, commandId)
632
+
633
+ const hashRegex = /[a-fA-F0-9]{64}/
634
+ const match = lastZkeyBlake2bHash.match(hashRegex)!
635
+
636
+ lastZkeyBlake2bHash = match.at(0)!
637
+
638
+ // re upload the formatted verification transcript
639
+ await uploadFileToBucket(
640
+ bucketName,
641
+ verificationTranscriptStoragePathAndFilename,
642
+ verificationTranscriptTemporaryLocalPath,
643
+ true
644
+ )
645
+ } else {
646
+ // Upload verification transcript.
647
+ /// nb. do not use multi-part upload here due to small file size.
648
+ await uploadFileToBucket(
649
+ bucketName,
650
+ verificationTranscriptStoragePathAndFilename,
651
+ verificationTranscriptTemporaryLocalPath,
652
+ true
653
+ )
654
+ }
608
655
 
609
- // Step (1.A.4).
610
- if (isContributionValid) {
611
- // Sleep ~3 seconds to wait for verification transcription.
612
- await sleep(3000)
656
+ // Compute verification transcript hash.
657
+ transcriptBlake2bHash = await blake512FromPath(verificationTranscriptTemporaryLocalPath)
613
658
 
614
- // Step (1.A.4.A.1).
615
- if (isUsingVM) {
616
- // Retrieve the contribution hash from the command output.
617
- lastZkeyBlake2bHash = await retrieveCommandOutput(ssm, vmInstanceId, commandId)
659
+ // Free resources by unlinking transcript temporary file.
660
+ fs.unlinkSync(verificationTranscriptTemporaryLocalPath)
618
661
 
619
- const hashRegex = /[a-fA-F0-9]{64}/
620
- const match = lastZkeyBlake2bHash.match(hashRegex)!
662
+ // Filter participant contributions to find the data related to the one verified.
663
+ const participantContributions = contributions.filter(
664
+ (contribution: Contribution) =>
665
+ !!contribution.hash && !!contribution.computationTime && !contribution.doc
666
+ )
621
667
 
622
- lastZkeyBlake2bHash = match.at(0)!
668
+ /// @dev (there must be only one contribution with an empty 'doc' field).
669
+ if (participantContributions.length !== 1)
670
+ logAndThrowError(SPECIFIC_ERRORS.SE_VERIFICATION_NO_PARTICIPANT_CONTRIBUTION_DATA)
671
+
672
+ // Get contribution computation time.
673
+ contributionComputationTime = contributions.at(0).computationTime
674
+
675
+ // Step (1.A.4.A.2).
676
+ batch.create(contributionDoc.ref, {
677
+ participantId: participantDoc.id,
678
+ contributionComputationTime,
679
+ verificationComputationTime: verifyCloudFunctionExecutionTime,
680
+ zkeyIndex: isFinalizing ? finalContributionIndex : lastZkeyIndex,
681
+ files: {
682
+ transcriptFilename: verificationTranscriptCompleteFilename,
683
+ lastZkeyFilename,
684
+ transcriptStoragePath: verificationTranscriptStoragePathAndFilename,
685
+ lastZkeyStoragePath,
686
+ transcriptBlake2bHash,
687
+ lastZkeyBlake2bHash
688
+ },
689
+ verificationSoftware: {
690
+ name: String(process.env.CUSTOM_CONTRIBUTION_VERIFICATION_SOFTWARE_NAME),
691
+ version: String(process.env.CUSTOM_CONTRIBUTION_VERIFICATION_SOFTWARE_VERSION),
692
+ commitHash: String(process.env.CUSTOM_CONTRIBUTION_VERIFICATION_SOFTWARE_COMMIT_HASH)
693
+ },
694
+ valid: isContributionValid,
695
+ lastUpdated: getCurrentServerTimestampInMillis()
696
+ })
623
697
 
624
- // re upload the formatted verification transcript
625
- await uploadFileToBucket(
626
- bucketName,
627
- verificationTranscriptStoragePathAndFilename,
628
- verificationTranscriptTemporaryLocalPath,
629
- true
630
- )
698
+ verifyContributionTimer.stop()
699
+ verifyCloudFunctionTime = verifyContributionTimer.ms()
631
700
  } else {
632
- // Upload verification transcript.
633
- /// nb. do not use multi-part upload here due to small file size.
634
- await uploadFileToBucket(
635
- bucketName,
636
- verificationTranscriptStoragePathAndFilename,
637
- verificationTranscriptTemporaryLocalPath,
638
- true
639
- )
701
+ // Step (1.A.4.B).
702
+
703
+ // Free-up storage by deleting invalid contribution.
704
+ await deleteObject(bucketName, lastZkeyStoragePath)
705
+
706
+ // Step (1.A.4.B.1).
707
+ batch.create(contributionDoc.ref, {
708
+ participantId: participantDoc.id,
709
+ verificationComputationTime: verifyCloudFunctionExecutionTime,
710
+ zkeyIndex: isFinalizing ? finalContributionIndex : lastZkeyIndex,
711
+ verificationSoftware: {
712
+ name: String(process.env.CUSTOM_CONTRIBUTION_VERIFICATION_SOFTWARE_NAME),
713
+ version: String(process.env.CUSTOM_CONTRIBUTION_VERIFICATION_SOFTWARE_VERSION),
714
+ commitHash: String(process.env.CUSTOM_CONTRIBUTION_VERIFICATION_SOFTWARE_COMMIT_HASH)
715
+ },
716
+ valid: isContributionValid,
717
+ lastUpdated: getCurrentServerTimestampInMillis()
718
+ })
640
719
  }
641
720
 
642
- // Compute verification transcript hash.
643
- transcriptBlake2bHash = await blake512FromPath(verificationTranscriptTemporaryLocalPath)
721
+ // Stop VM instance
722
+ if (isUsingVM) {
723
+ // using try and catch as the VM stopping function can throw
724
+ // however we want to continue without stopping as the
725
+ // verification was valid, and inform the coordinator
726
+ try {
727
+ await stopEC2Instance(ec2, vmInstanceId)
728
+ } catch (error: any) {
729
+ printLog(`Error while stopping VM instance ${vmInstanceId} - Error ${error}`, LogLevel.WARN)
730
+ }
731
+ }
732
+ // Step (1.A.4.C)
733
+ if (!isFinalizing) {
734
+ // Step (1.A.4.C.1)
735
+ // Compute new average contribution/verification time.
736
+ fullContributionTime = Number(verificationStartedAt) - Number(contributionStartedAt)
737
+
738
+ const newAvgContributionComputationTime =
739
+ avgContributionComputationTime > 0
740
+ ? (avgContributionComputationTime + contributionComputationTime) / 2
741
+ : contributionComputationTime
742
+ const newAvgFullContributionTime =
743
+ avgFullContributionTime > 0
744
+ ? (avgFullContributionTime + fullContributionTime) / 2
745
+ : fullContributionTime
746
+ const newAvgVerifyCloudFunctionTime =
747
+ avgVerifyCloudFunctionTime > 0
748
+ ? (avgVerifyCloudFunctionTime + verifyCloudFunctionTime) / 2
749
+ : verifyCloudFunctionTime
750
+
751
+ // Prepare tx to update circuit average contribution/verification time.
752
+ const updatedCircuitDoc = await getDocumentById(getCircuitsCollectionPath(ceremonyId), circuitId)
753
+ const { waitingQueue: updatedWaitingQueue } = updatedCircuitDoc.data()!
754
+ /// @dev this must happen only for valid contributions.
755
+ batch.update(circuitDoc.ref, {
756
+ avgTimings: {
757
+ contributionComputation: isContributionValid
758
+ ? newAvgContributionComputationTime
759
+ : avgContributionComputationTime,
760
+ fullContribution: isContributionValid
761
+ ? newAvgFullContributionTime
762
+ : avgFullContributionTime,
763
+ verifyCloudFunction: isContributionValid
764
+ ? newAvgVerifyCloudFunctionTime
765
+ : avgVerifyCloudFunctionTime
766
+ },
767
+ waitingQueue: {
768
+ ...updatedWaitingQueue,
769
+ completedContributions: isContributionValid
770
+ ? completedContributions + 1
771
+ : completedContributions,
772
+ failedContributions: isContributionValid ? failedContributions : failedContributions + 1
773
+ },
774
+ lastUpdated: getCurrentServerTimestampInMillis()
775
+ })
776
+ }
644
777
 
645
- // Free resources by unlinking transcript temporary file.
646
- fs.unlinkSync(verificationTranscriptTemporaryLocalPath)
778
+ // Step (2).
779
+ await batch.commit()
647
780
 
648
- // Filter participant contributions to find the data related to the one verified.
649
- const participantContributions = contributions.filter(
650
- (contribution: Contribution) =>
651
- !!contribution.hash && !!contribution.computationTime && !contribution.doc
781
+ printLog(
782
+ `The contribution #${
783
+ isFinalizing ? finalContributionIndex : lastZkeyIndex
784
+ } of circuit ${circuitId} (ceremony ${ceremonyId}) has been verified as ${
785
+ isContributionValid ? "valid" : "invalid"
786
+ } for the participant ${participantDoc.id}`,
787
+ LogLevel.INFO
652
788
  )
653
-
654
- /// @dev (there must be only one contribution with an empty 'doc' field).
655
- if (participantContributions.length !== 1)
656
- logAndThrowError(SPECIFIC_ERRORS.SE_VERIFICATION_NO_PARTICIPANT_CONTRIBUTION_DATA)
657
-
658
- // Get contribution computation time.
659
- contributionComputationTime = contributions.at(0).computationTime
660
-
661
- // Step (1.A.4.A.2).
662
- batch.create(contributionDoc.ref, {
663
- participantId: participantDoc.id,
664
- contributionComputationTime,
665
- verificationComputationTime: verifyCloudFunctionExecutionTime,
666
- zkeyIndex: isFinalizing ? finalContributionIndex : lastZkeyIndex,
667
- files: {
668
- transcriptFilename: verificationTranscriptCompleteFilename,
669
- lastZkeyFilename,
670
- transcriptStoragePath: verificationTranscriptStoragePathAndFilename,
671
- lastZkeyStoragePath,
672
- transcriptBlake2bHash,
673
- lastZkeyBlake2bHash
674
- },
675
- verificationSoftware: {
676
- name: String(process.env.CUSTOM_CONTRIBUTION_VERIFICATION_SOFTWARE_NAME),
677
- version: String(process.env.CUSTOM_CONTRIBUTION_VERIFICATION_SOFTWARE_VERSION),
678
- commitHash: String(process.env.CUSTOM_CONTRIBUTION_VERIFICATION_SOFTWARE_COMMIT_HASH)
679
- },
680
- valid: isContributionValid,
681
- lastUpdated: getCurrentServerTimestampInMillis()
682
- })
683
-
684
- verifyContributionTimer.stop()
685
- verifyCloudFunctionTime = verifyContributionTimer.ms()
686
- } else {
687
- // Step (1.A.4.B).
688
-
689
- // Free-up storage by deleting invalid contribution.
690
- await deleteObject(bucketName, lastZkeyStoragePath)
691
-
692
- // Step (1.A.4.B.1).
693
- batch.create(contributionDoc.ref, {
694
- participantId: participantDoc.id,
695
- verificationComputationTime: verifyCloudFunctionExecutionTime,
696
- zkeyIndex: isFinalizing ? finalContributionIndex : lastZkeyIndex,
697
- verificationSoftware: {
698
- name: String(process.env.CUSTOM_CONTRIBUTION_VERIFICATION_SOFTWARE_NAME),
699
- version: String(process.env.CUSTOM_CONTRIBUTION_VERIFICATION_SOFTWARE_VERSION),
700
- commitHash: String(process.env.CUSTOM_CONTRIBUTION_VERIFICATION_SOFTWARE_COMMIT_HASH)
701
- },
702
- valid: isContributionValid,
703
- lastUpdated: getCurrentServerTimestampInMillis()
704
- })
705
789
  }
706
790
 
707
- // Stop VM instance
708
- if (isUsingVM) {
709
- // using try and catch as the VM stopping function can throw
710
- // however we want to continue without stopping as the
711
- // verification was valid, and inform the coordinator
712
- try {
713
- await stopEC2Instance(ec2, vmInstanceId)
714
- } catch (error: any) {
715
- printLog(`Error while stopping VM instance ${vmInstanceId} - Error ${error}`, LogLevel.WARN)
716
- }
717
- }
718
- // Step (1.A.4.C)
719
- if (!isFinalizing) {
720
- // Step (1.A.4.C.1)
721
- // Compute new average contribution/verification time.
722
- fullContributionTime = Number(verificationStartedAt) - Number(contributionStartedAt)
723
-
724
- const newAvgContributionComputationTime =
725
- avgContributionComputationTime > 0
726
- ? (avgContributionComputationTime + contributionComputationTime) / 2
727
- : contributionComputationTime
728
- const newAvgFullContributionTime =
729
- avgFullContributionTime > 0
730
- ? (avgFullContributionTime + fullContributionTime) / 2
731
- : fullContributionTime
732
- const newAvgVerifyCloudFunctionTime =
733
- avgVerifyCloudFunctionTime > 0
734
- ? (avgVerifyCloudFunctionTime + verifyCloudFunctionTime) / 2
735
- : verifyCloudFunctionTime
736
-
737
- // Prepare tx to update circuit average contribution/verification time.
738
- const updatedCircuitDoc = await getDocumentById(getCircuitsCollectionPath(ceremonyId), circuitId)
739
- const { waitingQueue: updatedWaitingQueue } = updatedCircuitDoc.data()!
740
- /// @dev this must happen only for valid contributions.
741
- batch.update(circuitDoc.ref, {
742
- avgTimings: {
743
- contributionComputation: isContributionValid
744
- ? newAvgContributionComputationTime
745
- : avgContributionComputationTime,
746
- fullContribution: isContributionValid ? newAvgFullContributionTime : avgFullContributionTime,
747
- verifyCloudFunction: isContributionValid
748
- ? newAvgVerifyCloudFunctionTime
749
- : avgVerifyCloudFunctionTime
750
- },
751
- waitingQueue: {
752
- ...updatedWaitingQueue,
753
- completedContributions: isContributionValid
754
- ? completedContributions + 1
755
- : completedContributions,
756
- failedContributions: isContributionValid ? failedContributions : failedContributions + 1
757
- },
758
- lastUpdated: getCurrentServerTimestampInMillis()
759
- })
760
- }
791
+ // Step (1).
792
+ if (isContributing || isFinalizing) {
793
+ // Prepare timer.
794
+ verificationTaskTimer.start()
761
795
 
762
- // Step (2).
763
- await batch.commit()
796
+ // Step (1.A.3.0).
797
+ if (isUsingVM) {
798
+ printLog(`Starting the VM mechanism`, LogLevel.DEBUG)
764
799
 
765
- printLog(
766
- `The contribution #${
767
- isFinalizing ? finalContributionIndex : lastZkeyIndex
768
- } of circuit ${circuitId} (ceremony ${ceremonyId}) has been verified as ${
769
- isContributionValid ? "valid" : "invalid"
770
- } for the participant ${participantDoc.id}`,
771
- LogLevel.DEBUG
772
- )
773
- }
800
+ // Prepare for VM execution.
801
+ let isVMRunning = false // true when the VM is up, otherwise false.
774
802
 
775
- // Step (1).
776
- if (isContributing || isFinalizing) {
777
- // Prepare timer.
778
- verificationTaskTimer.start()
803
+ // Step (1.A.3.1).
804
+ await startEC2Instance(ec2, vmInstanceId)
779
805
 
780
- // Step (1.A.3.0).
781
- if (isUsingVM) {
782
- printLog(`Starting the VM mechanism`, LogLevel.DEBUG)
806
+ await sleep(60000) // nb. wait for VM startup (1 mins + retry).
783
807
 
784
- // Prepare for VM execution.
785
- let isVMRunning = false // true when the VM is up, otherwise false.
808
+ // Check if the startup is running.
809
+ isVMRunning = await checkIfVMRunning(ec2, vmInstanceId)
786
810
 
787
- // Step (1.A.3.1).
788
- await startEC2Instance(ec2, vmInstanceId)
811
+ printLog(`VM running: ${isVMRunning}`, LogLevel.DEBUG)
789
812
 
790
- await sleep(60000) // nb. wait for VM startup (1 mins + retry).
813
+ // Step (1.A.3.2).
814
+ // Prepare.
815
+ const verificationCommand = vmContributionVerificationCommand(
816
+ bucketName,
817
+ lastZkeyStoragePath,
818
+ verificationTranscriptStoragePathAndFilename
819
+ )
791
820
 
792
- // Check if the startup is running.
793
- isVMRunning = await checkIfVMRunning(ec2, vmInstanceId)
821
+ // Run.
822
+ commandId = await runCommandUsingSSM(ssm, vmInstanceId, verificationCommand)
794
823
 
795
- printLog(`VM running: ${isVMRunning}`, LogLevel.DEBUG)
824
+ printLog(`Starting the execution of command ${commandId}`, LogLevel.DEBUG)
796
825
 
797
- // Step (1.A.3.2).
798
- // Prepare.
799
- const verificationCommand = vmContributionVerificationCommand(
800
- bucketName,
801
- lastZkeyStoragePath,
802
- verificationTranscriptStoragePathAndFilename
803
- )
826
+ // Step (1.A.3.3).
827
+ return await waitForVMCommandExecution(ssm, vmInstanceId, commandId)
828
+ .then(async () => {
829
+ // Command execution successfully completed.
830
+ printLog(`Command ${commandId} execution has been successfully completed`, LogLevel.DEBUG)
831
+ await completeVerification()
832
+ })
833
+ .catch((error: any) => {
834
+ // Command execution aborted.
835
+ printLog(`Command ${commandId} execution has been aborted - Error ${error}`, LogLevel.WARN)
804
836
 
805
- // Run.
806
- commandId = await runCommandUsingSSM(ssm, vmInstanceId, verificationCommand)
837
+ logAndThrowError(COMMON_ERRORS.CM_INVALID_COMMAND_EXECUTION)
838
+ })
839
+ }
807
840
 
808
- printLog(`Starting the execution of command ${commandId}`, LogLevel.DEBUG)
841
+ // CF approach.
842
+ printLog(`CF mechanism`, LogLevel.DEBUG)
809
843
 
810
- // Step (1.A.3.3).
811
- return waitForVMCommandExecution(ssm, vmInstanceId, commandId)
812
- .then(async () => {
813
- // Command execution successfully completed.
814
- printLog(`Command ${commandId} execution has been successfully completed`, LogLevel.DEBUG)
815
- await completeVerification()
816
- })
817
- .catch((error: any) => {
818
- // Command execution aborted.
819
- printLog(`Command ${commandId} execution has been aborted - Error ${error}`, LogLevel.DEBUG)
844
+ const potStoragePath = getPotStorageFilePath(files.potFilename)
845
+ const firstZkeyStoragePath = getZkeyStorageFilePath(prefix, `${prefix}_${genesisZkeyIndex}.zkey`)
846
+ printLog(`pot file: ${potStoragePath}`, LogLevel.DEBUG)
847
+ printLog(`zkey file: ${firstZkeyStoragePath}`, LogLevel.DEBUG)
848
+ // Prepare temporary file paths.
849
+ // (nb. these are needed to download the necessary artifacts for verification from AWS S3).
850
+ verificationTranscriptTemporaryLocalPath = createTemporaryLocalPath(
851
+ verificationTranscriptCompleteFilename
852
+ )
853
+ const potTempFilePath = createTemporaryLocalPath(`${circuitId}_${participantDoc.id}.pot`)
854
+ const firstZkeyTempFilePath = createTemporaryLocalPath(`${circuitId}_${participantDoc.id}_genesis.zkey`)
855
+ const lastZkeyTempFilePath = createTemporaryLocalPath(`${circuitId}_${participantDoc.id}_last.zkey`)
856
+ printLog(`pot file: ${potTempFilePath}`, LogLevel.DEBUG)
857
+ printLog(`firstZkey file: ${firstZkeyTempFilePath}`, LogLevel.DEBUG)
858
+ printLog(`last zkey file: ${lastZkeyTempFilePath}`, LogLevel.DEBUG)
859
+
860
+ // Create and populate transcript.
861
+ const transcriptLogger = createCustomLoggerForFile(verificationTranscriptTemporaryLocalPath)
862
+ transcriptLogger.info(
863
+ `${
864
+ isFinalizing ? `Final verification` : `Verification`
865
+ } transcript for ${prefix} circuit Phase 2 contribution.\n${
866
+ isFinalizing ? `Coordinator ` : `Contributor # ${Number(lastZkeyIndex)}`
867
+ } (${contributorOrCoordinatorIdentifier})\n`
868
+ )
820
869
 
821
- logAndThrowError(COMMON_ERRORS.CM_INVALID_COMMAND_EXECUTION)
822
- })
823
- }
870
+ // Step (1.A.2).
871
+ await downloadArtifactFromS3Bucket(bucketName, potStoragePath, potTempFilePath)
872
+ await downloadArtifactFromS3Bucket(bucketName, firstZkeyStoragePath, firstZkeyTempFilePath)
873
+ await downloadArtifactFromS3Bucket(bucketName, lastZkeyStoragePath, lastZkeyTempFilePath)
874
+
875
+ // Step (1.A.4).
876
+ isContributionValid = await zKey.verifyFromInit(
877
+ firstZkeyTempFilePath,
878
+ potTempFilePath,
879
+ lastZkeyTempFilePath,
880
+ transcriptLogger
881
+ )
824
882
 
825
- // CF approach.
826
- printLog(`CF mechanism`, LogLevel.DEBUG)
827
-
828
- const potStoragePath = getPotStorageFilePath(files.potFilename)
829
- const firstZkeyStoragePath = getZkeyStorageFilePath(prefix, `${prefix}_${genesisZkeyIndex}.zkey`)
830
- // Prepare temporary file paths.
831
- // (nb. these are needed to download the necessary artifacts for verification from AWS S3).
832
- verificationTranscriptTemporaryLocalPath = createTemporaryLocalPath(verificationTranscriptCompleteFilename)
833
- const potTempFilePath = createTemporaryLocalPath(`${circuitId}_${participantDoc.id}.pot`)
834
- const firstZkeyTempFilePath = createTemporaryLocalPath(`${circuitId}_${participantDoc.id}_genesis.zkey`)
835
- const lastZkeyTempFilePath = createTemporaryLocalPath(`${circuitId}_${participantDoc.id}_last.zkey`)
836
-
837
- // Create and populate transcript.
838
- const transcriptLogger = createCustomLoggerForFile(verificationTranscriptTemporaryLocalPath)
839
- transcriptLogger.info(
840
- `${
841
- isFinalizing ? `Final verification` : `Verification`
842
- } transcript for ${prefix} circuit Phase 2 contribution.\n${
843
- isFinalizing ? `Coordinator ` : `Contributor # ${Number(lastZkeyIndex)}`
844
- } (${contributorOrCoordinatorIdentifier})\n`
845
- )
883
+ await dumpLog(verificationTranscriptTemporaryLocalPath)
846
884
 
847
- // Step (1.A.2).
848
- await downloadArtifactFromS3Bucket(bucketName, potStoragePath, potTempFilePath)
849
- await downloadArtifactFromS3Bucket(bucketName, firstZkeyStoragePath, firstZkeyTempFilePath)
850
- await downloadArtifactFromS3Bucket(bucketName, lastZkeyStoragePath, lastZkeyTempFilePath)
851
-
852
- // Step (1.A.4).
853
- isContributionValid = await zKey.verifyFromInit(
854
- firstZkeyTempFilePath,
855
- potTempFilePath,
856
- lastZkeyTempFilePath,
857
- transcriptLogger
858
- )
885
+ // Compute contribution hash.
886
+ lastZkeyBlake2bHash = await blake512FromPath(lastZkeyTempFilePath)
859
887
 
860
- // Compute contribution hash.
861
- lastZkeyBlake2bHash = await blake512FromPath(lastZkeyTempFilePath)
888
+ // Free resources by unlinking temporary folders.
889
+ // Do not free-up verification transcript path here.
890
+ try {
891
+ fs.unlinkSync(potTempFilePath)
892
+ fs.unlinkSync(firstZkeyTempFilePath)
893
+ fs.unlinkSync(lastZkeyTempFilePath)
894
+ } catch (error: any) {
895
+ printLog(`Error while unlinking temporary files - Error ${error}`, LogLevel.WARN)
896
+ }
862
897
 
863
- // Free resources by unlinking temporary folders.
864
- // Do not free-up verification transcript path here.
865
- try {
866
- fs.unlinkSync(potTempFilePath)
867
- fs.unlinkSync(firstZkeyTempFilePath)
868
- fs.unlinkSync(lastZkeyTempFilePath)
869
- } catch (error: any) {
870
- printLog(`Error while unlinking temporary files - Error ${error}`, LogLevel.WARN)
898
+ await completeVerification()
871
899
  }
872
900
 
873
- await completeVerification()
901
+ return null
902
+ } catch (error: any) {
903
+ logAndThrowError(makeError("unknown", error))
904
+ return null
874
905
  }
875
906
  }
876
907
  )
@@ -953,8 +984,8 @@ export const refreshParticipantAfterContributionVerification = functionsV1
953
984
  await batch.commit()
954
985
 
955
986
  printLog(
956
- `Participant ${participantId} refreshed after contribution ${createdContribution.id} - The participant was finalizing the ceremony ${isFinalizing}`,
957
- LogLevel.DEBUG
987
+ `Participant ${participantId} refreshed after contribution ${createdContribution.id} - The participant was finalizing the ceremony? ${isFinalizing}`,
988
+ LogLevel.INFO
958
989
  )
959
990
  })
960
991