@devtion/backend 0.0.0-c1f4cbe → 0.0.0-e22d20d

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.
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @module @p0tion/backend
3
- * @version 1.1.1
3
+ * @version 1.2.4
4
4
  * @file MPC Phase 2 backend for Firebase services management
5
5
  * @copyright Ethereum Foundation 2022
6
6
  * @license MIT
@@ -9,7 +9,7 @@
9
9
  import admin from 'firebase-admin';
10
10
  import * as functions from 'firebase-functions';
11
11
  import dotenv from 'dotenv';
12
- import { getCircuitsCollectionPath, getTimeoutsCollectionPath, commonTerms, finalContributionIndex, getContributionsCollectionPath, githubReputation, getBucketName, vmBootstrapCommand, vmDependenciesAndCacheArtifactsCommand, vmBootstrapScriptFilename, computeDiskSizeForVM, createEC2Instance, getParticipantsCollectionPath, terminateEC2Instance, formatZkeyIndex, getTranscriptStorageFilePath, getZkeyStorageFilePath, startEC2Instance, vmContributionVerificationCommand, runCommandUsingSSM, getPotStorageFilePath, genesisZkeyIndex, createCustomLoggerForFile, blake512FromPath, getVerificationKeyStorageFilePath, getVerifierContractStorageFilePath, computeSHA256ToHex, checkIfRunning, retrieveCommandOutput, stopEC2Instance, verificationKeyAcronym, verifierSmartContractAcronym, retrieveCommandStatus } from '@p0tion/actions';
12
+ import { getCircuitsCollectionPath, getTimeoutsCollectionPath, commonTerms, finalContributionIndex, getContributionsCollectionPath, githubReputation, getBucketName, vmBootstrapCommand, vmDependenciesAndCacheArtifactsCommand, vmBootstrapScriptFilename, computeDiskSizeForVM, createEC2Instance, getParticipantsCollectionPath, terminateEC2Instance, formatZkeyIndex, getTranscriptStorageFilePath, getZkeyStorageFilePath, retrieveCommandOutput, blake512FromPath, stopEC2Instance, startEC2Instance, vmContributionVerificationCommand, runCommandUsingSSM, getPotStorageFilePath, genesisZkeyIndex, createCustomLoggerForFile, getVerificationKeyStorageFilePath, getVerifierContractStorageFilePath, computeSHA256ToHex, checkIfRunning, verificationKeyAcronym, verifierSmartContractAcronym, retrieveCommandStatus } from '@p0tion/actions';
13
13
  import { encode } from 'html-entities';
14
14
  import { Timestamp, FieldValue } from 'firebase-admin/firestore';
15
15
  import { S3Client, GetObjectCommand, PutObjectCommand, DeleteObjectCommand, HeadBucketCommand, CreateBucketCommand, PutPublicAccessBlockCommand, PutBucketCorsCommand, HeadObjectCommand, CreateMultipartUploadCommand, UploadPartCommand, CompleteMultipartUploadCommand } from '@aws-sdk/client-s3';
@@ -536,7 +536,7 @@ dotenv.config();
536
536
  const registerAuthUser = functions
537
537
  .region("europe-west1")
538
538
  .runWith({
539
- memory: "512MB"
539
+ memory: "1GB"
540
540
  })
541
541
  .auth.user()
542
542
  .onCreate(async (user) => {
@@ -623,7 +623,7 @@ const registerAuthUser = functions
623
623
  const processSignUpWithCustomClaims = functions
624
624
  .region("europe-west1")
625
625
  .runWith({
626
- memory: "512MB"
626
+ memory: "1GB"
627
627
  })
628
628
  .auth.user()
629
629
  .onCreate(async (user) => {
@@ -664,7 +664,7 @@ dotenv.config();
664
664
  const startCeremony = functions
665
665
  .region("europe-west1")
666
666
  .runWith({
667
- memory: "512MB"
667
+ memory: "1GB"
668
668
  })
669
669
  .pubsub.schedule(`every 30 minutes`)
670
670
  .onRun(async () => {
@@ -686,7 +686,7 @@ const startCeremony = functions
686
686
  const stopCeremony = functions
687
687
  .region("europe-west1")
688
688
  .runWith({
689
- memory: "512MB"
689
+ memory: "1GB"
690
690
  })
691
691
  .pubsub.schedule(`every 30 minutes`)
692
692
  .onRun(async () => {
@@ -708,7 +708,7 @@ const stopCeremony = functions
708
708
  const setupCeremony = functions
709
709
  .region("europe-west1")
710
710
  .runWith({
711
- memory: "512MB"
711
+ memory: "1GB"
712
712
  })
713
713
  .https.onCall(async (data, context) => {
714
714
  // Check if the user has the coordinator claim.
@@ -833,7 +833,7 @@ const initEmptyWaitingQueueForCircuit = functions
833
833
  const finalizeCeremony = functions
834
834
  .region("europe-west1")
835
835
  .runWith({
836
- memory: "512MB"
836
+ memory: "1GB"
837
837
  })
838
838
  .https.onCall(async (data, context) => {
839
839
  if (!context.auth || !context.auth.token.coordinator)
@@ -909,7 +909,7 @@ dotenv.config();
909
909
  const checkParticipantForCeremony = functions
910
910
  .region("europe-west1")
911
911
  .runWith({
912
- memory: "512MB"
912
+ memory: "1GB"
913
913
  })
914
914
  .https.onCall(async (data, context) => {
915
915
  if (!context.auth || (!context.auth.token.participant && !context.auth.token.coordinator))
@@ -1013,7 +1013,7 @@ const checkParticipantForCeremony = functions
1013
1013
  const progressToNextCircuitForContribution = functions
1014
1014
  .region("europe-west1")
1015
1015
  .runWith({
1016
- memory: "512MB"
1016
+ memory: "1GB"
1017
1017
  })
1018
1018
  .https.onCall(async (data, context) => {
1019
1019
  if (!context.auth || (!context.auth.token.participant && !context.auth.token.coordinator))
@@ -1060,7 +1060,7 @@ const progressToNextCircuitForContribution = functions
1060
1060
  const progressToNextContributionStep = functions
1061
1061
  .region("europe-west1")
1062
1062
  .runWith({
1063
- memory: "512MB"
1063
+ memory: "1GB"
1064
1064
  })
1065
1065
  .https.onCall(async (data, context) => {
1066
1066
  if (!context.auth || (!context.auth.token.participant && !context.auth.token.coordinator))
@@ -1111,7 +1111,7 @@ const progressToNextContributionStep = functions
1111
1111
  const permanentlyStoreCurrentContributionTimeAndHash = functions
1112
1112
  .region("europe-west1")
1113
1113
  .runWith({
1114
- memory: "512MB"
1114
+ memory: "1GB"
1115
1115
  })
1116
1116
  .https.onCall(async (data, context) => {
1117
1117
  if (!context.auth || (!context.auth.token.participant && !context.auth.token.coordinator))
@@ -1153,7 +1153,7 @@ const permanentlyStoreCurrentContributionTimeAndHash = functions
1153
1153
  const temporaryStoreCurrentContributionMultiPartUploadId = functions
1154
1154
  .region("europe-west1")
1155
1155
  .runWith({
1156
- memory: "512MB"
1156
+ memory: "1GB"
1157
1157
  })
1158
1158
  .https.onCall(async (data, context) => {
1159
1159
  if (!context.auth || (!context.auth.token.participant && !context.auth.token.coordinator))
@@ -1191,7 +1191,7 @@ const temporaryStoreCurrentContributionMultiPartUploadId = functions
1191
1191
  const temporaryStoreCurrentContributionUploadedChunkData = functions
1192
1192
  .region("europe-west1")
1193
1193
  .runWith({
1194
- memory: "512MB"
1194
+ memory: "1GB"
1195
1195
  })
1196
1196
  .https.onCall(async (data, context) => {
1197
1197
  if (!context.auth || (!context.auth.token.participant && !context.auth.token.coordinator))
@@ -1233,7 +1233,7 @@ const temporaryStoreCurrentContributionUploadedChunkData = functions
1233
1233
  const checkAndPrepareCoordinatorForFinalization = functions
1234
1234
  .region("europe-west1")
1235
1235
  .runWith({
1236
- memory: "512MB"
1236
+ memory: "1GB"
1237
1237
  })
1238
1238
  .https.onCall(async (data, context) => {
1239
1239
  if (!context.auth || !context.auth.token.coordinator)
@@ -1473,7 +1473,7 @@ const waitForVMCommandExecution = (ssm, vmInstanceId, commandId) => new Promise(
1473
1473
  const coordinateCeremonyParticipant = functionsV1
1474
1474
  .region("europe-west1")
1475
1475
  .runWith({
1476
- memory: "512MB"
1476
+ memory: "1GB"
1477
1477
  })
1478
1478
  .firestore.document(`${commonTerms.collections.ceremonies.name}/{ceremonyId}/${commonTerms.collections.participants.name}/{participantId}`)
1479
1479
  .onUpdate(async (participantChanges) => {
@@ -1573,296 +1573,301 @@ const checkIfVMRunning = async (ec2, vmInstanceId, attempts = 5) => {
1573
1573
  * 2) Send all updates atomically to the Firestore database.
1574
1574
  */
1575
1575
  const verifycontribution = functionsV2.https.onCall({ memory: "16GiB", timeoutSeconds: 3600, region: "europe-west1" }, async (request) => {
1576
- if (!request.auth || (!request.auth.token.participant && !request.auth.token.coordinator))
1577
- logAndThrowError(SPECIFIC_ERRORS.SE_AUTH_NO_CURRENT_AUTH_USER);
1578
- if (!request.data.ceremonyId ||
1579
- !request.data.circuitId ||
1580
- !request.data.contributorOrCoordinatorIdentifier ||
1581
- !request.data.bucketName)
1582
- logAndThrowError(COMMON_ERRORS.CM_MISSING_OR_WRONG_INPUT_DATA);
1583
- if (!process.env.CUSTOM_CONTRIBUTION_VERIFICATION_SOFTWARE_NAME ||
1584
- !process.env.CUSTOM_CONTRIBUTION_VERIFICATION_SOFTWARE_VERSION ||
1585
- !process.env.CUSTOM_CONTRIBUTION_VERIFICATION_SOFTWARE_COMMIT_HASH)
1586
- logAndThrowError(COMMON_ERRORS.CM_WRONG_CONFIGURATION);
1587
- // Step (0).
1588
- // Prepare and start timer.
1589
- const verifyContributionTimer = new Timer({ label: commonTerms.cloudFunctionsNames.verifyContribution });
1590
- verifyContributionTimer.start();
1591
- // Get DB.
1592
- const firestore = admin.firestore();
1593
- // Prepare batch of txs.
1594
- const batch = firestore.batch();
1595
- // Extract data.
1596
- const { ceremonyId, circuitId, contributorOrCoordinatorIdentifier, bucketName } = request.data;
1597
- const userId = request.auth?.uid;
1598
- // Look for the ceremony, circuit and participant document.
1599
- const ceremonyDoc = await getDocumentById(commonTerms.collections.ceremonies.name, ceremonyId);
1600
- const circuitDoc = await getDocumentById(getCircuitsCollectionPath(ceremonyId), circuitId);
1601
- const participantDoc = await getDocumentById(getParticipantsCollectionPath(ceremonyId), userId);
1602
- if (!ceremonyDoc.data() || !circuitDoc.data() || !participantDoc.data())
1603
- logAndThrowError(COMMON_ERRORS.CM_INEXISTENT_DOCUMENT_DATA);
1604
- // Extract documents data.
1605
- const { state } = ceremonyDoc.data();
1606
- const { status, contributions, verificationStartedAt, contributionStartedAt } = participantDoc.data();
1607
- const { waitingQueue, prefix, avgTimings, verification, files } = circuitDoc.data();
1608
- const { completedContributions, failedContributions } = waitingQueue;
1609
- const { contributionComputation: avgContributionComputationTime, fullContribution: avgFullContributionTime, verifyCloudFunction: avgVerifyCloudFunctionTime } = avgTimings;
1610
- const { cfOrVm, vm } = verification;
1611
- // we might not have it if the circuit is not using VM.
1612
- let vmInstanceId = "";
1613
- if (vm)
1614
- vmInstanceId = vm.vmInstanceId;
1615
- // Define pre-conditions.
1616
- const isFinalizing = state === "CLOSED" /* CeremonyState.CLOSED */ && request.auth && request.auth.token.coordinator; // true only when the coordinator verifies the final contributions.
1617
- const isContributing = status === "CONTRIBUTING" /* ParticipantStatus.CONTRIBUTING */;
1618
- const isUsingVM = cfOrVm === "VM" /* CircuitContributionVerificationMechanism.VM */ && !!vmInstanceId;
1619
- // Prepare state.
1620
- let isContributionValid = false;
1621
- let verifyCloudFunctionExecutionTime = 0; // time spent while executing the verify contribution cloud function.
1622
- let verifyCloudFunctionTime = 0; // time spent while executing the core business logic of this cloud function.
1623
- let fullContributionTime = 0; // time spent while doing non-verification contributions tasks (download, compute, upload).
1624
- let contributionComputationTime = 0; // time spent while computing the contribution.
1625
- let lastZkeyBlake2bHash = ""; // the Blake2B hash of the last zKey.
1626
- let verificationTranscriptTemporaryLocalPath = ""; // the local temporary path for the verification transcript.
1627
- let transcriptBlake2bHash = ""; // the Blake2B hash of the verification transcript.
1628
- let commandId = ""; // the unique identifier of the VM command.
1629
- // Derive necessary data.
1630
- const lastZkeyIndex = formatZkeyIndex(completedContributions + 1);
1631
- const verificationTranscriptCompleteFilename = `${prefix}_${isFinalizing
1632
- ? `${contributorOrCoordinatorIdentifier}_${finalContributionIndex}_verification_transcript.log`
1633
- : `${lastZkeyIndex}_${contributorOrCoordinatorIdentifier}_verification_transcript.log`}`;
1634
- const lastZkeyFilename = `${prefix}_${isFinalizing ? finalContributionIndex : lastZkeyIndex}.zkey`;
1635
- // Prepare state for VM verification (if needed).
1636
- const ec2 = await createEC2Client();
1637
- const ssm = await createSSMClient();
1638
- // Step (1.A.1).
1639
- // Get storage paths.
1640
- const verificationTranscriptStoragePathAndFilename = getTranscriptStorageFilePath(prefix, verificationTranscriptCompleteFilename);
1641
- // the zKey storage path is required to be sent to the VM api
1642
- const lastZkeyStoragePath = getZkeyStorageFilePath(prefix, `${prefix}_${isFinalizing ? finalContributionIndex : lastZkeyIndex}.zkey`);
1643
- const verificationTaskTimer = new Timer({ label: `${ceremonyId}-${circuitId}-${participantDoc.id}` });
1644
- const completeVerification = async () => {
1645
- // Stop verification task timer.
1646
- printLog("Completing verification", LogLevel.DEBUG);
1647
- verificationTaskTimer.stop();
1648
- verifyCloudFunctionExecutionTime = verificationTaskTimer.ms();
1649
- if (isUsingVM) {
1650
- // Create temporary path.
1651
- verificationTranscriptTemporaryLocalPath = createTemporaryLocalPath(`${circuitId}_${participantDoc.id}.log`);
1652
- await sleep(1000); // wait 1s for file creation.
1653
- // Download from bucket.
1654
- // nb. the transcript MUST be uploaded from the VM by verification commands.
1655
- await downloadArtifactFromS3Bucket(bucketName, verificationTranscriptStoragePathAndFilename, verificationTranscriptTemporaryLocalPath);
1656
- // Read the verification trascript and validate data by checking for core info ("ZKey Ok!").
1657
- const content = fs.readFileSync(verificationTranscriptTemporaryLocalPath, "utf-8");
1658
- if (content.includes("ZKey Ok!"))
1659
- isContributionValid = true;
1660
- // If the contribution is valid, then format and store the trascript.
1576
+ try {
1577
+ if (!request.auth || (!request.auth.token.participant && !request.auth.token.coordinator))
1578
+ logAndThrowError(SPECIFIC_ERRORS.SE_AUTH_NO_CURRENT_AUTH_USER);
1579
+ if (!request.data.ceremonyId ||
1580
+ !request.data.circuitId ||
1581
+ !request.data.contributorOrCoordinatorIdentifier ||
1582
+ !request.data.bucketName)
1583
+ logAndThrowError(COMMON_ERRORS.CM_MISSING_OR_WRONG_INPUT_DATA);
1584
+ if (!process.env.CUSTOM_CONTRIBUTION_VERIFICATION_SOFTWARE_NAME ||
1585
+ !process.env.CUSTOM_CONTRIBUTION_VERIFICATION_SOFTWARE_VERSION ||
1586
+ !process.env.CUSTOM_CONTRIBUTION_VERIFICATION_SOFTWARE_COMMIT_HASH)
1587
+ logAndThrowError(COMMON_ERRORS.CM_WRONG_CONFIGURATION);
1588
+ // Step (0).
1589
+ // Prepare and start timer.
1590
+ const verifyContributionTimer = new Timer({ label: commonTerms.cloudFunctionsNames.verifyContribution });
1591
+ verifyContributionTimer.start();
1592
+ // Get DB.
1593
+ const firestore = admin.firestore();
1594
+ // Prepare batch of txs.
1595
+ const batch = firestore.batch();
1596
+ // Extract data.
1597
+ const { ceremonyId, circuitId, contributorOrCoordinatorIdentifier, bucketName } = request.data;
1598
+ const userId = request.auth?.uid;
1599
+ // Look for the ceremony, circuit and participant document.
1600
+ const ceremonyDoc = await getDocumentById(commonTerms.collections.ceremonies.name, ceremonyId);
1601
+ const circuitDoc = await getDocumentById(getCircuitsCollectionPath(ceremonyId), circuitId);
1602
+ const participantDoc = await getDocumentById(getParticipantsCollectionPath(ceremonyId), userId);
1603
+ if (!ceremonyDoc.data() || !circuitDoc.data() || !participantDoc.data())
1604
+ logAndThrowError(COMMON_ERRORS.CM_INEXISTENT_DOCUMENT_DATA);
1605
+ // Extract documents data.
1606
+ const { state } = ceremonyDoc.data();
1607
+ const { status, contributions, verificationStartedAt, contributionStartedAt } = participantDoc.data();
1608
+ const { waitingQueue, prefix, avgTimings, verification, files } = circuitDoc.data();
1609
+ const { completedContributions, failedContributions } = waitingQueue;
1610
+ const { contributionComputation: avgContributionComputationTime, fullContribution: avgFullContributionTime, verifyCloudFunction: avgVerifyCloudFunctionTime } = avgTimings;
1611
+ const { cfOrVm, vm } = verification;
1612
+ // we might not have it if the circuit is not using VM.
1613
+ let vmInstanceId = "";
1614
+ if (vm)
1615
+ vmInstanceId = vm.vmInstanceId;
1616
+ // Define pre-conditions.
1617
+ const isFinalizing = state === "CLOSED" /* CeremonyState.CLOSED */ && request.auth && request.auth.token.coordinator; // true only when the coordinator verifies the final contributions.
1618
+ const isContributing = status === "CONTRIBUTING" /* ParticipantStatus.CONTRIBUTING */;
1619
+ const isUsingVM = cfOrVm === "VM" /* CircuitContributionVerificationMechanism.VM */ && !!vmInstanceId;
1620
+ // Prepare state.
1621
+ let isContributionValid = false;
1622
+ let verifyCloudFunctionExecutionTime = 0; // time spent while executing the verify contribution cloud function.
1623
+ let verifyCloudFunctionTime = 0; // time spent while executing the core business logic of this cloud function.
1624
+ let fullContributionTime = 0; // time spent while doing non-verification contributions tasks (download, compute, upload).
1625
+ let contributionComputationTime = 0; // time spent while computing the contribution.
1626
+ let lastZkeyBlake2bHash = ""; // the Blake2B hash of the last zKey.
1627
+ let verificationTranscriptTemporaryLocalPath = ""; // the local temporary path for the verification transcript.
1628
+ let transcriptBlake2bHash = ""; // the Blake2B hash of the verification transcript.
1629
+ let commandId = ""; // the unique identifier of the VM command.
1630
+ // Derive necessary data.
1631
+ const lastZkeyIndex = formatZkeyIndex(completedContributions + 1);
1632
+ const verificationTranscriptCompleteFilename = `${prefix}_${isFinalizing
1633
+ ? `${contributorOrCoordinatorIdentifier}_${finalContributionIndex}_verification_transcript.log`
1634
+ : `${lastZkeyIndex}_${contributorOrCoordinatorIdentifier}_verification_transcript.log`}`;
1635
+ const lastZkeyFilename = `${prefix}_${isFinalizing ? finalContributionIndex : lastZkeyIndex}.zkey`;
1636
+ // Prepare state for VM verification (if needed).
1637
+ const ec2 = await createEC2Client();
1638
+ const ssm = await createSSMClient();
1639
+ // Step (1.A.1).
1640
+ // Get storage paths.
1641
+ const verificationTranscriptStoragePathAndFilename = getTranscriptStorageFilePath(prefix, verificationTranscriptCompleteFilename);
1642
+ // the zKey storage path is required to be sent to the VM api
1643
+ const lastZkeyStoragePath = getZkeyStorageFilePath(prefix, `${prefix}_${isFinalizing ? finalContributionIndex : lastZkeyIndex}.zkey`);
1644
+ const verificationTaskTimer = new Timer({ label: `${ceremonyId}-${circuitId}-${participantDoc.id}` });
1645
+ const completeVerification = async () => {
1646
+ // Stop verification task timer.
1647
+ printLog("Completing verification", LogLevel.DEBUG);
1648
+ verificationTaskTimer.stop();
1649
+ verifyCloudFunctionExecutionTime = verificationTaskTimer.ms();
1650
+ if (isUsingVM) {
1651
+ // Create temporary path.
1652
+ verificationTranscriptTemporaryLocalPath = createTemporaryLocalPath(`${circuitId}_${participantDoc.id}.log`);
1653
+ await sleep(1000); // wait 1s for file creation.
1654
+ // Download from bucket.
1655
+ // nb. the transcript MUST be uploaded from the VM by verification commands.
1656
+ await downloadArtifactFromS3Bucket(bucketName, verificationTranscriptStoragePathAndFilename, verificationTranscriptTemporaryLocalPath);
1657
+ // Read the verification trascript and validate data by checking for core info ("ZKey Ok!").
1658
+ const content = fs.readFileSync(verificationTranscriptTemporaryLocalPath, "utf-8");
1659
+ if (content.includes("ZKey Ok!"))
1660
+ isContributionValid = true;
1661
+ // If the contribution is valid, then format and store the trascript.
1662
+ if (isContributionValid) {
1663
+ // eslint-disable-next-line no-control-regex
1664
+ const updated = content.replace(/\x1b[[0-9;]*m/g, "");
1665
+ fs.writeFileSync(verificationTranscriptTemporaryLocalPath, updated);
1666
+ }
1667
+ }
1668
+ printLog(`The contribution has been verified - Result ${isContributionValid}`, LogLevel.DEBUG);
1669
+ // Create a new contribution document.
1670
+ const contributionDoc = await firestore
1671
+ .collection(getContributionsCollectionPath(ceremonyId, circuitId))
1672
+ .doc()
1673
+ .get();
1674
+ // Step (1.A.4).
1661
1675
  if (isContributionValid) {
1662
- // eslint-disable-next-line no-control-regex
1663
- const updated = content.replace(/\x1b[[0-9;]*m/g, "");
1664
- fs.writeFileSync(verificationTranscriptTemporaryLocalPath, updated);
1676
+ // Sleep ~3 seconds to wait for verification transcription.
1677
+ await sleep(3000);
1678
+ // Step (1.A.4.A.1).
1679
+ if (isUsingVM) {
1680
+ // Retrieve the contribution hash from the command output.
1681
+ lastZkeyBlake2bHash = await retrieveCommandOutput(ssm, vmInstanceId, commandId);
1682
+ const hashRegex = /[a-fA-F0-9]{64}/;
1683
+ const match = lastZkeyBlake2bHash.match(hashRegex);
1684
+ lastZkeyBlake2bHash = match.at(0);
1685
+ // re upload the formatted verification transcript
1686
+ await uploadFileToBucket(bucketName, verificationTranscriptStoragePathAndFilename, verificationTranscriptTemporaryLocalPath, true);
1687
+ }
1688
+ else {
1689
+ // Upload verification transcript.
1690
+ /// nb. do not use multi-part upload here due to small file size.
1691
+ await uploadFileToBucket(bucketName, verificationTranscriptStoragePathAndFilename, verificationTranscriptTemporaryLocalPath, true);
1692
+ }
1693
+ // Compute verification transcript hash.
1694
+ transcriptBlake2bHash = await blake512FromPath(verificationTranscriptTemporaryLocalPath);
1695
+ // Free resources by unlinking transcript temporary file.
1696
+ fs.unlinkSync(verificationTranscriptTemporaryLocalPath);
1697
+ // Filter participant contributions to find the data related to the one verified.
1698
+ const participantContributions = contributions.filter((contribution) => !!contribution.hash && !!contribution.computationTime && !contribution.doc);
1699
+ /// @dev (there must be only one contribution with an empty 'doc' field).
1700
+ if (participantContributions.length !== 1)
1701
+ logAndThrowError(SPECIFIC_ERRORS.SE_VERIFICATION_NO_PARTICIPANT_CONTRIBUTION_DATA);
1702
+ // Get contribution computation time.
1703
+ contributionComputationTime = contributions.at(0).computationTime;
1704
+ // Step (1.A.4.A.2).
1705
+ batch.create(contributionDoc.ref, {
1706
+ participantId: participantDoc.id,
1707
+ contributionComputationTime,
1708
+ verificationComputationTime: verifyCloudFunctionExecutionTime,
1709
+ zkeyIndex: isFinalizing ? finalContributionIndex : lastZkeyIndex,
1710
+ files: {
1711
+ transcriptFilename: verificationTranscriptCompleteFilename,
1712
+ lastZkeyFilename,
1713
+ transcriptStoragePath: verificationTranscriptStoragePathAndFilename,
1714
+ lastZkeyStoragePath,
1715
+ transcriptBlake2bHash,
1716
+ lastZkeyBlake2bHash
1717
+ },
1718
+ verificationSoftware: {
1719
+ name: String(process.env.CUSTOM_CONTRIBUTION_VERIFICATION_SOFTWARE_NAME),
1720
+ version: String(process.env.CUSTOM_CONTRIBUTION_VERIFICATION_SOFTWARE_VERSION),
1721
+ commitHash: String(process.env.CUSTOM_CONTRIBUTION_VERIFICATION_SOFTWARE_COMMIT_HASH)
1722
+ },
1723
+ valid: isContributionValid,
1724
+ lastUpdated: getCurrentServerTimestampInMillis()
1725
+ });
1726
+ verifyContributionTimer.stop();
1727
+ verifyCloudFunctionTime = verifyContributionTimer.ms();
1665
1728
  }
1666
- }
1667
- printLog(`The contribution has been verified - Result ${isContributionValid}`, LogLevel.DEBUG);
1668
- // Create a new contribution document.
1669
- const contributionDoc = await firestore
1670
- .collection(getContributionsCollectionPath(ceremonyId, circuitId))
1671
- .doc()
1672
- .get();
1673
- // Step (1.A.4).
1674
- if (isContributionValid) {
1675
- // Sleep ~3 seconds to wait for verification transcription.
1676
- await sleep(3000);
1677
- // Step (1.A.4.A.1).
1729
+ else {
1730
+ // Step (1.A.4.B).
1731
+ // Free-up storage by deleting invalid contribution.
1732
+ await deleteObject(bucketName, lastZkeyStoragePath);
1733
+ // Step (1.A.4.B.1).
1734
+ batch.create(contributionDoc.ref, {
1735
+ participantId: participantDoc.id,
1736
+ verificationComputationTime: verifyCloudFunctionExecutionTime,
1737
+ zkeyIndex: isFinalizing ? finalContributionIndex : lastZkeyIndex,
1738
+ verificationSoftware: {
1739
+ name: String(process.env.CUSTOM_CONTRIBUTION_VERIFICATION_SOFTWARE_NAME),
1740
+ version: String(process.env.CUSTOM_CONTRIBUTION_VERIFICATION_SOFTWARE_VERSION),
1741
+ commitHash: String(process.env.CUSTOM_CONTRIBUTION_VERIFICATION_SOFTWARE_COMMIT_HASH)
1742
+ },
1743
+ valid: isContributionValid,
1744
+ lastUpdated: getCurrentServerTimestampInMillis()
1745
+ });
1746
+ }
1747
+ // Stop VM instance
1678
1748
  if (isUsingVM) {
1679
- // Retrieve the contribution hash from the command output.
1680
- lastZkeyBlake2bHash = await retrieveCommandOutput(ssm, vmInstanceId, commandId);
1681
- const hashRegex = /[a-fA-F0-9]{64}/;
1682
- const match = lastZkeyBlake2bHash.match(hashRegex);
1683
- lastZkeyBlake2bHash = match.at(0);
1684
- // re upload the formatted verification transcript
1685
- await uploadFileToBucket(bucketName, verificationTranscriptStoragePathAndFilename, verificationTranscriptTemporaryLocalPath, true);
1749
+ // using try and catch as the VM stopping function can throw
1750
+ // however we want to continue without stopping as the
1751
+ // verification was valid, and inform the coordinator
1752
+ try {
1753
+ await stopEC2Instance(ec2, vmInstanceId);
1754
+ }
1755
+ catch (error) {
1756
+ printLog(`Error while stopping VM instance ${vmInstanceId} - Error ${error}`, LogLevel.WARN);
1757
+ }
1686
1758
  }
1687
- else {
1688
- // Upload verification transcript.
1689
- /// nb. do not use multi-part upload here due to small file size.
1690
- await uploadFileToBucket(bucketName, verificationTranscriptStoragePathAndFilename, verificationTranscriptTemporaryLocalPath, true);
1759
+ // Step (1.A.4.C)
1760
+ if (!isFinalizing) {
1761
+ // Step (1.A.4.C.1)
1762
+ // Compute new average contribution/verification time.
1763
+ fullContributionTime = Number(verificationStartedAt) - Number(contributionStartedAt);
1764
+ const newAvgContributionComputationTime = avgContributionComputationTime > 0
1765
+ ? (avgContributionComputationTime + contributionComputationTime) / 2
1766
+ : contributionComputationTime;
1767
+ const newAvgFullContributionTime = avgFullContributionTime > 0
1768
+ ? (avgFullContributionTime + fullContributionTime) / 2
1769
+ : fullContributionTime;
1770
+ const newAvgVerifyCloudFunctionTime = avgVerifyCloudFunctionTime > 0
1771
+ ? (avgVerifyCloudFunctionTime + verifyCloudFunctionTime) / 2
1772
+ : verifyCloudFunctionTime;
1773
+ // Prepare tx to update circuit average contribution/verification time.
1774
+ const updatedCircuitDoc = await getDocumentById(getCircuitsCollectionPath(ceremonyId), circuitId);
1775
+ const { waitingQueue: updatedWaitingQueue } = updatedCircuitDoc.data();
1776
+ /// @dev this must happen only for valid contributions.
1777
+ batch.update(circuitDoc.ref, {
1778
+ avgTimings: {
1779
+ contributionComputation: isContributionValid
1780
+ ? newAvgContributionComputationTime
1781
+ : avgContributionComputationTime,
1782
+ fullContribution: isContributionValid ? newAvgFullContributionTime : avgFullContributionTime,
1783
+ verifyCloudFunction: isContributionValid
1784
+ ? newAvgVerifyCloudFunctionTime
1785
+ : avgVerifyCloudFunctionTime
1786
+ },
1787
+ waitingQueue: {
1788
+ ...updatedWaitingQueue,
1789
+ completedContributions: isContributionValid
1790
+ ? completedContributions + 1
1791
+ : completedContributions,
1792
+ failedContributions: isContributionValid ? failedContributions : failedContributions + 1
1793
+ },
1794
+ lastUpdated: getCurrentServerTimestampInMillis()
1795
+ });
1691
1796
  }
1692
- // Compute verification transcript hash.
1693
- transcriptBlake2bHash = await blake512FromPath(verificationTranscriptTemporaryLocalPath);
1694
- // Free resources by unlinking transcript temporary file.
1695
- fs.unlinkSync(verificationTranscriptTemporaryLocalPath);
1696
- // Filter participant contributions to find the data related to the one verified.
1697
- const participantContributions = contributions.filter((contribution) => !!contribution.hash && !!contribution.computationTime && !contribution.doc);
1698
- /// @dev (there must be only one contribution with an empty 'doc' field).
1699
- if (participantContributions.length !== 1)
1700
- logAndThrowError(SPECIFIC_ERRORS.SE_VERIFICATION_NO_PARTICIPANT_CONTRIBUTION_DATA);
1701
- // Get contribution computation time.
1702
- contributionComputationTime = contributions.at(0).computationTime;
1703
- // Step (1.A.4.A.2).
1704
- batch.create(contributionDoc.ref, {
1705
- participantId: participantDoc.id,
1706
- contributionComputationTime,
1707
- verificationComputationTime: verifyCloudFunctionExecutionTime,
1708
- zkeyIndex: isFinalizing ? finalContributionIndex : lastZkeyIndex,
1709
- files: {
1710
- transcriptFilename: verificationTranscriptCompleteFilename,
1711
- lastZkeyFilename,
1712
- transcriptStoragePath: verificationTranscriptStoragePathAndFilename,
1713
- lastZkeyStoragePath,
1714
- transcriptBlake2bHash,
1715
- lastZkeyBlake2bHash
1716
- },
1717
- verificationSoftware: {
1718
- name: String(process.env.CUSTOM_CONTRIBUTION_VERIFICATION_SOFTWARE_NAME),
1719
- version: String(process.env.CUSTOM_CONTRIBUTION_VERIFICATION_SOFTWARE_VERSION),
1720
- commitHash: String(process.env.CUSTOM_CONTRIBUTION_VERIFICATION_SOFTWARE_COMMIT_HASH)
1721
- },
1722
- valid: isContributionValid,
1723
- lastUpdated: getCurrentServerTimestampInMillis()
1724
- });
1725
- verifyContributionTimer.stop();
1726
- verifyCloudFunctionTime = verifyContributionTimer.ms();
1727
- }
1728
- else {
1729
- // Step (1.A.4.B).
1730
- // Free-up storage by deleting invalid contribution.
1731
- await deleteObject(bucketName, lastZkeyStoragePath);
1732
- // Step (1.A.4.B.1).
1733
- batch.create(contributionDoc.ref, {
1734
- participantId: participantDoc.id,
1735
- verificationComputationTime: verifyCloudFunctionExecutionTime,
1736
- zkeyIndex: isFinalizing ? finalContributionIndex : lastZkeyIndex,
1737
- verificationSoftware: {
1738
- name: String(process.env.CUSTOM_CONTRIBUTION_VERIFICATION_SOFTWARE_NAME),
1739
- version: String(process.env.CUSTOM_CONTRIBUTION_VERIFICATION_SOFTWARE_VERSION),
1740
- commitHash: String(process.env.CUSTOM_CONTRIBUTION_VERIFICATION_SOFTWARE_COMMIT_HASH)
1741
- },
1742
- valid: isContributionValid,
1743
- lastUpdated: getCurrentServerTimestampInMillis()
1744
- });
1745
- }
1746
- // Stop VM instance
1747
- if (isUsingVM) {
1748
- // using try and catch as the VM stopping function can throw
1749
- // however we want to continue without stopping as the
1750
- // verification was valid, and inform the coordinator
1797
+ // Step (2).
1798
+ await batch.commit();
1799
+ printLog(`The contribution #${isFinalizing ? finalContributionIndex : lastZkeyIndex} of circuit ${circuitId} (ceremony ${ceremonyId}) has been verified as ${isContributionValid ? "valid" : "invalid"} for the participant ${participantDoc.id}`, LogLevel.DEBUG);
1800
+ };
1801
+ // Step (1).
1802
+ if (isContributing || isFinalizing) {
1803
+ // Prepare timer.
1804
+ verificationTaskTimer.start();
1805
+ // Step (1.A.3.0).
1806
+ if (isUsingVM) {
1807
+ printLog(`Starting the VM mechanism`, LogLevel.DEBUG);
1808
+ // Prepare for VM execution.
1809
+ let isVMRunning = false; // true when the VM is up, otherwise false.
1810
+ // Step (1.A.3.1).
1811
+ await startEC2Instance(ec2, vmInstanceId);
1812
+ await sleep(60000); // nb. wait for VM startup (1 mins + retry).
1813
+ // Check if the startup is running.
1814
+ isVMRunning = await checkIfVMRunning(ec2, vmInstanceId);
1815
+ printLog(`VM running: ${isVMRunning}`, LogLevel.DEBUG);
1816
+ // Step (1.A.3.2).
1817
+ // Prepare.
1818
+ const verificationCommand = vmContributionVerificationCommand(bucketName, lastZkeyStoragePath, verificationTranscriptStoragePathAndFilename);
1819
+ // Run.
1820
+ commandId = await runCommandUsingSSM(ssm, vmInstanceId, verificationCommand);
1821
+ printLog(`Starting the execution of command ${commandId}`, LogLevel.DEBUG);
1822
+ // Step (1.A.3.3).
1823
+ return waitForVMCommandExecution(ssm, vmInstanceId, commandId)
1824
+ .then(async () => {
1825
+ // Command execution successfully completed.
1826
+ printLog(`Command ${commandId} execution has been successfully completed`, LogLevel.DEBUG);
1827
+ await completeVerification();
1828
+ })
1829
+ .catch((error) => {
1830
+ // Command execution aborted.
1831
+ printLog(`Command ${commandId} execution has been aborted - Error ${error}`, LogLevel.DEBUG);
1832
+ logAndThrowError(COMMON_ERRORS.CM_INVALID_COMMAND_EXECUTION);
1833
+ });
1834
+ }
1835
+ // CF approach.
1836
+ printLog(`CF mechanism`, LogLevel.DEBUG);
1837
+ const potStoragePath = getPotStorageFilePath(files.potFilename);
1838
+ const firstZkeyStoragePath = getZkeyStorageFilePath(prefix, `${prefix}_${genesisZkeyIndex}.zkey`);
1839
+ // Prepare temporary file paths.
1840
+ // (nb. these are needed to download the necessary artifacts for verification from AWS S3).
1841
+ verificationTranscriptTemporaryLocalPath = createTemporaryLocalPath(verificationTranscriptCompleteFilename);
1842
+ const potTempFilePath = createTemporaryLocalPath(`${circuitId}_${participantDoc.id}.pot`);
1843
+ const firstZkeyTempFilePath = createTemporaryLocalPath(`${circuitId}_${participantDoc.id}_genesis.zkey`);
1844
+ const lastZkeyTempFilePath = createTemporaryLocalPath(`${circuitId}_${participantDoc.id}_last.zkey`);
1845
+ // Create and populate transcript.
1846
+ const transcriptLogger = createCustomLoggerForFile(verificationTranscriptTemporaryLocalPath);
1847
+ transcriptLogger.info(`${isFinalizing ? `Final verification` : `Verification`} transcript for ${prefix} circuit Phase 2 contribution.\n${isFinalizing ? `Coordinator ` : `Contributor # ${Number(lastZkeyIndex)}`} (${contributorOrCoordinatorIdentifier})\n`);
1848
+ // Step (1.A.2).
1849
+ await downloadArtifactFromS3Bucket(bucketName, potStoragePath, potTempFilePath);
1850
+ await downloadArtifactFromS3Bucket(bucketName, firstZkeyStoragePath, firstZkeyTempFilePath);
1851
+ await downloadArtifactFromS3Bucket(bucketName, lastZkeyStoragePath, lastZkeyTempFilePath);
1852
+ // Step (1.A.4).
1853
+ isContributionValid = await zKey.verifyFromInit(firstZkeyTempFilePath, potTempFilePath, lastZkeyTempFilePath, transcriptLogger);
1854
+ // Compute contribution hash.
1855
+ lastZkeyBlake2bHash = await blake512FromPath(lastZkeyTempFilePath);
1856
+ // Free resources by unlinking temporary folders.
1857
+ // Do not free-up verification transcript path here.
1751
1858
  try {
1752
- await stopEC2Instance(ec2, vmInstanceId);
1859
+ fs.unlinkSync(potTempFilePath);
1860
+ fs.unlinkSync(firstZkeyTempFilePath);
1861
+ fs.unlinkSync(lastZkeyTempFilePath);
1753
1862
  }
1754
1863
  catch (error) {
1755
- printLog(`Error while stopping VM instance ${vmInstanceId} - Error ${error}`, LogLevel.WARN);
1864
+ printLog(`Error while unlinking temporary files - Error ${error}`, LogLevel.WARN);
1756
1865
  }
1866
+ await completeVerification();
1757
1867
  }
1758
- // Step (1.A.4.C)
1759
- if (!isFinalizing) {
1760
- // Step (1.A.4.C.1)
1761
- // Compute new average contribution/verification time.
1762
- fullContributionTime = Number(verificationStartedAt) - Number(contributionStartedAt);
1763
- const newAvgContributionComputationTime = avgContributionComputationTime > 0
1764
- ? (avgContributionComputationTime + contributionComputationTime) / 2
1765
- : contributionComputationTime;
1766
- const newAvgFullContributionTime = avgFullContributionTime > 0
1767
- ? (avgFullContributionTime + fullContributionTime) / 2
1768
- : fullContributionTime;
1769
- const newAvgVerifyCloudFunctionTime = avgVerifyCloudFunctionTime > 0
1770
- ? (avgVerifyCloudFunctionTime + verifyCloudFunctionTime) / 2
1771
- : verifyCloudFunctionTime;
1772
- // Prepare tx to update circuit average contribution/verification time.
1773
- const updatedCircuitDoc = await getDocumentById(getCircuitsCollectionPath(ceremonyId), circuitId);
1774
- const { waitingQueue: updatedWaitingQueue } = updatedCircuitDoc.data();
1775
- /// @dev this must happen only for valid contributions.
1776
- batch.update(circuitDoc.ref, {
1777
- avgTimings: {
1778
- contributionComputation: isContributionValid
1779
- ? newAvgContributionComputationTime
1780
- : avgContributionComputationTime,
1781
- fullContribution: isContributionValid ? newAvgFullContributionTime : avgFullContributionTime,
1782
- verifyCloudFunction: isContributionValid
1783
- ? newAvgVerifyCloudFunctionTime
1784
- : avgVerifyCloudFunctionTime
1785
- },
1786
- waitingQueue: {
1787
- ...updatedWaitingQueue,
1788
- completedContributions: isContributionValid
1789
- ? completedContributions + 1
1790
- : completedContributions,
1791
- failedContributions: isContributionValid ? failedContributions : failedContributions + 1
1792
- },
1793
- lastUpdated: getCurrentServerTimestampInMillis()
1794
- });
1795
- }
1796
- // Step (2).
1797
- await batch.commit();
1798
- printLog(`The contribution #${isFinalizing ? finalContributionIndex : lastZkeyIndex} of circuit ${circuitId} (ceremony ${ceremonyId}) has been verified as ${isContributionValid ? "valid" : "invalid"} for the participant ${participantDoc.id}`, LogLevel.DEBUG);
1799
- };
1800
- // Step (1).
1801
- if (isContributing || isFinalizing) {
1802
- // Prepare timer.
1803
- verificationTaskTimer.start();
1804
- // Step (1.A.3.0).
1805
- if (isUsingVM) {
1806
- printLog(`Starting the VM mechanism`, LogLevel.DEBUG);
1807
- // Prepare for VM execution.
1808
- let isVMRunning = false; // true when the VM is up, otherwise false.
1809
- // Step (1.A.3.1).
1810
- await startEC2Instance(ec2, vmInstanceId);
1811
- await sleep(60000); // nb. wait for VM startup (1 mins + retry).
1812
- // Check if the startup is running.
1813
- isVMRunning = await checkIfVMRunning(ec2, vmInstanceId);
1814
- printLog(`VM running: ${isVMRunning}`, LogLevel.DEBUG);
1815
- // Step (1.A.3.2).
1816
- // Prepare.
1817
- const verificationCommand = vmContributionVerificationCommand(bucketName, lastZkeyStoragePath, verificationTranscriptStoragePathAndFilename);
1818
- // Run.
1819
- commandId = await runCommandUsingSSM(ssm, vmInstanceId, verificationCommand);
1820
- printLog(`Starting the execution of command ${commandId}`, LogLevel.DEBUG);
1821
- // Step (1.A.3.3).
1822
- return waitForVMCommandExecution(ssm, vmInstanceId, commandId)
1823
- .then(async () => {
1824
- // Command execution successfully completed.
1825
- printLog(`Command ${commandId} execution has been successfully completed`, LogLevel.DEBUG);
1826
- await completeVerification();
1827
- })
1828
- .catch((error) => {
1829
- // Command execution aborted.
1830
- printLog(`Command ${commandId} execution has been aborted - Error ${error}`, LogLevel.DEBUG);
1831
- logAndThrowError(COMMON_ERRORS.CM_INVALID_COMMAND_EXECUTION);
1832
- });
1833
- }
1834
- // CF approach.
1835
- printLog(`CF mechanism`, LogLevel.DEBUG);
1836
- const potStoragePath = getPotStorageFilePath(files.potFilename);
1837
- const firstZkeyStoragePath = getZkeyStorageFilePath(prefix, `${prefix}_${genesisZkeyIndex}.zkey`);
1838
- // Prepare temporary file paths.
1839
- // (nb. these are needed to download the necessary artifacts for verification from AWS S3).
1840
- verificationTranscriptTemporaryLocalPath = createTemporaryLocalPath(verificationTranscriptCompleteFilename);
1841
- const potTempFilePath = createTemporaryLocalPath(`${circuitId}_${participantDoc.id}.pot`);
1842
- const firstZkeyTempFilePath = createTemporaryLocalPath(`${circuitId}_${participantDoc.id}_genesis.zkey`);
1843
- const lastZkeyTempFilePath = createTemporaryLocalPath(`${circuitId}_${participantDoc.id}_last.zkey`);
1844
- // Create and populate transcript.
1845
- const transcriptLogger = createCustomLoggerForFile(verificationTranscriptTemporaryLocalPath);
1846
- transcriptLogger.info(`${isFinalizing ? `Final verification` : `Verification`} transcript for ${prefix} circuit Phase 2 contribution.\n${isFinalizing ? `Coordinator ` : `Contributor # ${Number(lastZkeyIndex)}`} (${contributorOrCoordinatorIdentifier})\n`);
1847
- // Step (1.A.2).
1848
- await downloadArtifactFromS3Bucket(bucketName, potStoragePath, potTempFilePath);
1849
- await downloadArtifactFromS3Bucket(bucketName, firstZkeyStoragePath, firstZkeyTempFilePath);
1850
- await downloadArtifactFromS3Bucket(bucketName, lastZkeyStoragePath, lastZkeyTempFilePath);
1851
- // Step (1.A.4).
1852
- isContributionValid = await zKey.verifyFromInit(firstZkeyTempFilePath, potTempFilePath, lastZkeyTempFilePath, transcriptLogger);
1853
- // Compute contribution hash.
1854
- lastZkeyBlake2bHash = await blake512FromPath(lastZkeyTempFilePath);
1855
- // Free resources by unlinking temporary folders.
1856
- // Do not free-up verification transcript path here.
1857
- try {
1858
- fs.unlinkSync(potTempFilePath);
1859
- fs.unlinkSync(firstZkeyTempFilePath);
1860
- fs.unlinkSync(lastZkeyTempFilePath);
1861
- }
1862
- catch (error) {
1863
- printLog(`Error while unlinking temporary files - Error ${error}`, LogLevel.WARN);
1864
- }
1865
- await completeVerification();
1868
+ }
1869
+ catch (error) {
1870
+ logAndThrowError(makeError("unknown", error));
1866
1871
  }
1867
1872
  });
1868
1873
  /**
@@ -1873,7 +1878,7 @@ const verifycontribution = functionsV2.https.onCall({ memory: "16GiB", timeoutSe
1873
1878
  const refreshParticipantAfterContributionVerification = functionsV1
1874
1879
  .region("europe-west1")
1875
1880
  .runWith({
1876
- memory: "512MB"
1881
+ memory: "1GB"
1877
1882
  })
1878
1883
  .firestore.document(`/${commonTerms.collections.ceremonies.name}/{ceremony}/${commonTerms.collections.circuits.name}/{circuit}/${commonTerms.collections.contributions.name}/{contributions}`)
1879
1884
  .onCreate(async (createdContribution) => {
@@ -1934,7 +1939,7 @@ const refreshParticipantAfterContributionVerification = functionsV1
1934
1939
  const finalizeCircuit = functionsV1
1935
1940
  .region("europe-west1")
1936
1941
  .runWith({
1937
- memory: "512MB"
1942
+ memory: "1GB"
1938
1943
  })
1939
1944
  .https.onCall(async (data, context) => {
1940
1945
  if (!context.auth || !context.auth.token.coordinator)
@@ -2078,7 +2083,7 @@ const checkIfBucketIsDedicatedToCeremony = async (bucketName) => {
2078
2083
  const createBucket = functions
2079
2084
  .region("europe-west1")
2080
2085
  .runWith({
2081
- memory: "512MB"
2086
+ memory: "1GB"
2082
2087
  })
2083
2088
  .https.onCall(async (data, context) => {
2084
2089
  // Check if the user has the coordinator claim.
@@ -2168,7 +2173,7 @@ const createBucket = functions
2168
2173
  const checkIfObjectExist = functions
2169
2174
  .region("europe-west1")
2170
2175
  .runWith({
2171
- memory: "512MB"
2176
+ memory: "1GB"
2172
2177
  })
2173
2178
  .https.onCall(async (data, context) => {
2174
2179
  // Check if the user has the coordinator claim.
@@ -2214,7 +2219,7 @@ const checkIfObjectExist = functions
2214
2219
  const generateGetObjectPreSignedUrl = functions
2215
2220
  .region("europe-west1")
2216
2221
  .runWith({
2217
- memory: "512MB"
2222
+ memory: "1GB"
2218
2223
  })
2219
2224
  .https.onCall(async (data, context) => {
2220
2225
  if (!context.auth)
@@ -2254,7 +2259,7 @@ const generateGetObjectPreSignedUrl = functions
2254
2259
  const startMultiPartUpload = functions
2255
2260
  .region("europe-west1")
2256
2261
  .runWith({
2257
- memory: "512MB"
2262
+ memory: "2GB"
2258
2263
  })
2259
2264
  .https.onCall(async (data, context) => {
2260
2265
  if (!context.auth || (!context.auth.token.participant && !context.auth.token.coordinator))
@@ -2309,7 +2314,7 @@ const startMultiPartUpload = functions
2309
2314
  const generatePreSignedUrlsParts = functions
2310
2315
  .region("europe-west1")
2311
2316
  .runWith({
2312
- memory: "512MB",
2317
+ memory: "1GB",
2313
2318
  timeoutSeconds: 300
2314
2319
  })
2315
2320
  .https.onCall(async (data, context) => {
@@ -2370,7 +2375,7 @@ const generatePreSignedUrlsParts = functions
2370
2375
  const completeMultiPartUpload = functions
2371
2376
  .region("europe-west1")
2372
2377
  .runWith({
2373
- memory: "512MB"
2378
+ memory: "2GB"
2374
2379
  })
2375
2380
  .https.onCall(async (data, context) => {
2376
2381
  if (!context.auth || (!context.auth.token.participant && !context.auth.token.coordinator))
@@ -2584,7 +2589,7 @@ const checkNonceOfSIWEAddress = functions
2584
2589
  const auth = getAuth();
2585
2590
  // check nonce
2586
2591
  const parts = result.sub.split("|");
2587
- const address = decodeURIComponent(parts[2]).split("eip155:534352:")[1];
2592
+ const address = decodeURIComponent(parts[2]).split(":")[2];
2588
2593
  const minimumNonce = Number(process.env.ETH_MINIMUM_NONCE);
2589
2594
  const nonceBlockHeight = "latest"; // process.env.ETH_NONCE_BLOCK_HEIGHT
2590
2595
  // look up nonce for address @block
@@ -2651,7 +2656,7 @@ dotenv.config();
2651
2656
  const checkAndRemoveBlockingContributor = functions
2652
2657
  .region("europe-west1")
2653
2658
  .runWith({
2654
- memory: "512MB"
2659
+ memory: "1GB"
2655
2660
  })
2656
2661
  .pubsub.schedule("every 1 minutes")
2657
2662
  .onRun(async () => {
@@ -2720,7 +2725,8 @@ const checkAndRemoveBlockingContributor = functions
2720
2725
  if (timeoutExpirationDateInMsForBlockingContributor < currentServerTimestamp &&
2721
2726
  (contributionStep === "DOWNLOADING" /* ParticipantContributionStep.DOWNLOADING */ ||
2722
2727
  contributionStep === "COMPUTING" /* ParticipantContributionStep.COMPUTING */ ||
2723
- contributionStep === "UPLOADING" /* ParticipantContributionStep.UPLOADING */))
2728
+ contributionStep === "UPLOADING" /* ParticipantContributionStep.UPLOADING */ ||
2729
+ contributionStep === "COMPLETED" /* ParticipantContributionStep.COMPLETED */))
2724
2730
  timeoutType = "BLOCKING_CONTRIBUTION" /* TimeoutType.BLOCKING_CONTRIBUTION */;
2725
2731
  if (timeoutExpirationDateInMsForVerificationCloudFunction > 0 &&
2726
2732
  timeoutExpirationDateInMsForVerificationCloudFunction < currentServerTimestamp &&
@@ -2797,7 +2803,7 @@ const checkAndRemoveBlockingContributor = functions
2797
2803
  const resumeContributionAfterTimeoutExpiration = functions
2798
2804
  .region("europe-west1")
2799
2805
  .runWith({
2800
- memory: "512MB"
2806
+ memory: "1GB"
2801
2807
  })
2802
2808
  .https.onCall(async (data, context) => {
2803
2809
  if (!context.auth || (!context.auth.token.participant && !context.auth.token.coordinator))