@devtion/backend 0.0.0-56491a8 → 0.0.0-57a8ab9
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 +7 -7
- package/dist/src/functions/index.js +287 -106
- package/dist/src/functions/index.mjs +291 -111
- package/dist/types/functions/bandada.d.ts +4 -0
- package/dist/types/functions/bandada.d.ts.map +1 -0
- package/dist/types/functions/ceremony.d.ts.map +1 -1
- package/dist/types/functions/circuit.d.ts.map +1 -1
- package/dist/types/functions/index.d.ts +1 -0
- package/dist/types/functions/index.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 +2 -1
- package/dist/types/lib/errors.d.ts.map +1 -1
- package/dist/types/lib/utils.d.ts.map +1 -1
- package/dist/types/types/index.d.ts +25 -0
- package/dist/types/types/index.d.ts.map +1 -1
- package/package.json +4 -3
- package/src/functions/bandada.ts +156 -0
- package/src/functions/ceremony.ts +8 -3
- package/src/functions/circuit.ts +137 -115
- package/src/functions/index.ts +1 -0
- package/src/functions/participant.ts +8 -8
- package/src/functions/storage.ts +6 -3
- package/src/functions/timeout.ts +3 -2
- package/src/functions/user.ts +20 -10
- package/src/lib/errors.ts +6 -1
- package/src/lib/utils.ts +10 -8
- package/src/types/declarations.d.ts +1 -0
- package/src/types/index.ts +27 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @module @
|
|
3
|
-
* @version 1.
|
|
2
|
+
* @module @p0tion/backend
|
|
3
|
+
* @version 1.1.1
|
|
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,
|
|
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';
|
|
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';
|
|
@@ -19,7 +19,7 @@ import { pipeline } from 'node:stream';
|
|
|
19
19
|
import { promisify } from 'node:util';
|
|
20
20
|
import fs, { readFileSync } from 'fs';
|
|
21
21
|
import mime from 'mime-types';
|
|
22
|
-
import { setTimeout } from 'timers/promises';
|
|
22
|
+
import { setTimeout as setTimeout$1 } from 'timers/promises';
|
|
23
23
|
import fetch from '@adobe/node-fetch-retry';
|
|
24
24
|
import path from 'path';
|
|
25
25
|
import os from 'os';
|
|
@@ -28,7 +28,9 @@ import { EC2Client } from '@aws-sdk/client-ec2';
|
|
|
28
28
|
import * as functionsV1 from 'firebase-functions/v1';
|
|
29
29
|
import * as functionsV2 from 'firebase-functions/v2';
|
|
30
30
|
import { Timer } from 'timer-node';
|
|
31
|
-
import { zKey } from 'snarkjs';
|
|
31
|
+
import { zKey, groth16 } from 'snarkjs';
|
|
32
|
+
import { ApiSdk } from '@bandada/api-sdk';
|
|
33
|
+
import { getAuth } from 'firebase-admin/auth';
|
|
32
34
|
|
|
33
35
|
/**
|
|
34
36
|
* Log levels.
|
|
@@ -49,7 +51,7 @@ var LogLevel;
|
|
|
49
51
|
* @notice the set of Firebase Functions status codes. The codes are the same at the
|
|
50
52
|
* ones exposed by {@link https://github.com/grpc/grpc/blob/master/doc/statuscodes.md | gRPC}.
|
|
51
53
|
* @param errorCode <FunctionsErrorCode> - the set of possible error codes.
|
|
52
|
-
* @param message <string> - the error
|
|
54
|
+
* @param message <string> - the error message.
|
|
53
55
|
* @param [details] <string> - the details of the error (optional).
|
|
54
56
|
* @returns <HttpsError>
|
|
55
57
|
*/
|
|
@@ -121,7 +123,8 @@ const SPECIFIC_ERRORS = {
|
|
|
121
123
|
SE_VM_FAILED_COMMAND_EXECUTION: makeError("failed-precondition", "VM command execution failed", "Please, contact the coordinator if this error persists."),
|
|
122
124
|
SE_VM_TIMEDOUT_COMMAND_EXECUTION: makeError("deadline-exceeded", "VM command execution took too long and has been timed-out", "Please, contact the coordinator if this error persists."),
|
|
123
125
|
SE_VM_CANCELLED_COMMAND_EXECUTION: makeError("cancelled", "VM command execution has been cancelled", "Please, contact the coordinator if this error persists."),
|
|
124
|
-
SE_VM_DELAYED_COMMAND_EXECUTION: makeError("unavailable", "VM command execution has been delayed since there were no available instance at the moment", "Please, contact the coordinator if this error persists.")
|
|
126
|
+
SE_VM_DELAYED_COMMAND_EXECUTION: makeError("unavailable", "VM command execution has been delayed since there were no available instance at the moment", "Please, contact the coordinator if this error persists."),
|
|
127
|
+
SE_VM_UNKNOWN_COMMAND_STATUS: makeError("unavailable", "VM command execution has failed due to an unknown status code", "Please, contact the coordinator if this error persists.")
|
|
125
128
|
};
|
|
126
129
|
/**
|
|
127
130
|
* A set of common errors.
|
|
@@ -191,7 +194,7 @@ const getCurrentServerTimestampInMillis = () => Timestamp.now().toMillis();
|
|
|
191
194
|
* Interrupt the current execution for a specified amount of time.
|
|
192
195
|
* @param ms <number> - the amount of time expressed in milliseconds.
|
|
193
196
|
*/
|
|
194
|
-
const sleep = async (ms) => setTimeout(ms);
|
|
197
|
+
const sleep = async (ms) => setTimeout$1(ms);
|
|
195
198
|
/**
|
|
196
199
|
* Query for ceremony circuits.
|
|
197
200
|
* @notice the order by sequence position is fundamental to maintain parallelism among contributions for different circuits.
|
|
@@ -264,7 +267,7 @@ const queryOpenedCeremonies = async () => {
|
|
|
264
267
|
const getCircuitDocumentByPosition = async (ceremonyId, sequencePosition) => {
|
|
265
268
|
// Query for all ceremony circuits.
|
|
266
269
|
const circuits = await getCeremonyCircuits(ceremonyId);
|
|
267
|
-
// Apply a filter using the sequence
|
|
270
|
+
// Apply a filter using the sequence position.
|
|
268
271
|
const matchedCircuits = circuits.filter((circuit) => circuit.data().sequencePosition === sequencePosition);
|
|
269
272
|
if (matchedCircuits.length !== 1)
|
|
270
273
|
logAndThrowError(COMMON_ERRORS.CM_NO_CIRCUIT_FOR_GIVEN_SEQUENCE_POSITION);
|
|
@@ -305,7 +308,7 @@ const downloadArtifactFromS3Bucket = async (bucketName, objectKey, localFilePath
|
|
|
305
308
|
const writeStream = createWriteStream(localFilePath);
|
|
306
309
|
const streamPipeline = promisify(pipeline);
|
|
307
310
|
await streamPipeline(response.body, writeStream);
|
|
308
|
-
writeStream.on(
|
|
311
|
+
writeStream.on("finish", () => {
|
|
309
312
|
writeStream.end();
|
|
310
313
|
});
|
|
311
314
|
};
|
|
@@ -429,12 +432,14 @@ const htmlEncodeCircuitData = (circuitDocument) => ({
|
|
|
429
432
|
const getGitHubVariables = () => {
|
|
430
433
|
if (!process.env.GITHUB_MINIMUM_FOLLOWERS ||
|
|
431
434
|
!process.env.GITHUB_MINIMUM_FOLLOWING ||
|
|
432
|
-
!process.env.GITHUB_MINIMUM_PUBLIC_REPOS
|
|
435
|
+
!process.env.GITHUB_MINIMUM_PUBLIC_REPOS ||
|
|
436
|
+
!process.env.GITHUB_MINIMUM_AGE)
|
|
433
437
|
logAndThrowError(COMMON_ERRORS.CM_WRONG_CONFIGURATION);
|
|
434
438
|
return {
|
|
435
439
|
minimumFollowers: Number(process.env.GITHUB_MINIMUM_FOLLOWERS),
|
|
436
440
|
minimumFollowing: Number(process.env.GITHUB_MINIMUM_FOLLOWING),
|
|
437
|
-
minimumPublicRepos: Number(process.env.GITHUB_MINIMUM_PUBLIC_REPOS)
|
|
441
|
+
minimumPublicRepos: Number(process.env.GITHUB_MINIMUM_PUBLIC_REPOS),
|
|
442
|
+
minimumAge: Number(process.env.GITHUB_MINIMUM_AGE)
|
|
438
443
|
};
|
|
439
444
|
};
|
|
440
445
|
/**
|
|
@@ -444,7 +449,7 @@ const getGitHubVariables = () => {
|
|
|
444
449
|
const getAWSVariables = () => {
|
|
445
450
|
if (!process.env.AWS_ACCESS_KEY_ID ||
|
|
446
451
|
!process.env.AWS_SECRET_ACCESS_KEY ||
|
|
447
|
-
!process.env.
|
|
452
|
+
!process.env.AWS_INSTANCE_PROFILE_ARN ||
|
|
448
453
|
!process.env.AWS_AMI_ID ||
|
|
449
454
|
!process.env.AWS_SNS_TOPIC_ARN)
|
|
450
455
|
logAndThrowError(COMMON_ERRORS.CM_WRONG_CONFIGURATION);
|
|
@@ -452,7 +457,7 @@ const getAWSVariables = () => {
|
|
|
452
457
|
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
|
|
453
458
|
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
|
|
454
459
|
region: process.env.AWS_REGION || "eu-central-1",
|
|
455
|
-
|
|
460
|
+
instanceProfileArn: process.env.AWS_INSTANCE_PROFILE_ARN,
|
|
456
461
|
amiId: process.env.AWS_AMI_ID,
|
|
457
462
|
snsTopic: process.env.AWS_SNS_TOPIC_ARN
|
|
458
463
|
};
|
|
@@ -530,16 +535,18 @@ const registerAuthUser = functions
|
|
|
530
535
|
email === process.env.CUSTOM_CLAIMS_COORDINATOR_EMAIL_ADDRESS_OR_DOMAIN)) {
|
|
531
536
|
const auth = admin.auth();
|
|
532
537
|
// if provider == github.com let's use our functions to check the user's reputation
|
|
533
|
-
if (user.providerData[0].providerId === "github.com") {
|
|
538
|
+
if (user.providerData.length > 0 && user.providerData[0].providerId === "github.com") {
|
|
534
539
|
const vars = getGitHubVariables();
|
|
535
540
|
// this return true or false
|
|
536
541
|
try {
|
|
537
|
-
const { reputable, avatarUrl: avatarURL } = await githubReputation(user.providerData[0].uid, vars.minimumFollowing, vars.minimumFollowers, vars.minimumPublicRepos);
|
|
542
|
+
const { reputable, avatarUrl: avatarURL } = await githubReputation(user.providerData[0].uid, vars.minimumFollowing, vars.minimumFollowers, vars.minimumPublicRepos, vars.minimumAge);
|
|
538
543
|
if (!reputable) {
|
|
539
544
|
// Delete user
|
|
540
545
|
await auth.deleteUser(user.uid);
|
|
541
546
|
// Throw error
|
|
542
|
-
logAndThrowError(makeError("permission-denied", "The user is not allowed to sign up because their Github reputation is not high enough.", `The user ${user.displayName === "Null" || user.displayName === null
|
|
547
|
+
logAndThrowError(makeError("permission-denied", "The user is not allowed to sign up because their Github reputation is not high enough.", `The user ${user.displayName === "Null" || user.displayName === null
|
|
548
|
+
? user.uid
|
|
549
|
+
: user.displayName} is not allowed to sign up because their Github reputation is not high enough. Please contact the administrator if you think this is a mistake.`));
|
|
543
550
|
}
|
|
544
551
|
// store locally
|
|
545
552
|
avatarUrl = avatarURL;
|
|
@@ -554,13 +561,13 @@ const registerAuthUser = functions
|
|
|
554
561
|
}
|
|
555
562
|
// Set document (nb. we refer to providerData[0] because we use Github OAuth provider only).
|
|
556
563
|
// In future releases we might want to loop through the providerData array as we support
|
|
557
|
-
// more providers.
|
|
564
|
+
// more providers.
|
|
558
565
|
await userRef.set({
|
|
559
566
|
name: encodedDisplayName,
|
|
560
567
|
encodedDisplayName,
|
|
561
568
|
// Metadata.
|
|
562
569
|
creationTime,
|
|
563
|
-
lastSignInTime,
|
|
570
|
+
lastSignInTime: lastSignInTime || creationTime,
|
|
564
571
|
// Optional.
|
|
565
572
|
email: email || "",
|
|
566
573
|
emailVerified: emailVerified || false,
|
|
@@ -570,7 +577,7 @@ const registerAuthUser = functions
|
|
|
570
577
|
// we want to create a new collection for the users to store the avatars
|
|
571
578
|
const avatarRef = firestore.collection(commonTerms.collections.avatars.name).doc(uid);
|
|
572
579
|
await avatarRef.set({
|
|
573
|
-
avatarUrl: avatarUrl || ""
|
|
580
|
+
avatarUrl: avatarUrl || ""
|
|
574
581
|
});
|
|
575
582
|
printLog(`Authenticated user document with identifier ${uid} has been correctly stored`, LogLevel.DEBUG);
|
|
576
583
|
printLog(`Authenticated user avatar with identifier ${uid} has been correctly stored`, LogLevel.DEBUG);
|
|
@@ -710,7 +717,7 @@ const setupCeremony = functions
|
|
|
710
717
|
// Check if using the VM approach for contribution verification.
|
|
711
718
|
if (circuit.verification.cfOrVm === "VM" /* CircuitContributionVerificationMechanism.VM */) {
|
|
712
719
|
// VM command to be run at the startup.
|
|
713
|
-
const startupCommand = vmBootstrapCommand(bucketName);
|
|
720
|
+
const startupCommand = vmBootstrapCommand(`${bucketName}/circuits/${circuit.name}`);
|
|
714
721
|
// Get EC2 client.
|
|
715
722
|
const ec2Client = await createEC2Client();
|
|
716
723
|
// Get AWS variables.
|
|
@@ -719,7 +726,8 @@ const setupCeremony = functions
|
|
|
719
726
|
const vmCommands = vmDependenciesAndCacheArtifactsCommand(`${bucketName}/${circuit.files?.initialZkeyStoragePath}`, `${bucketName}/${circuit.files?.potStoragePath}`, snsTopic, region);
|
|
720
727
|
printLog(`Check VM dependencies and cache artifacts commands ${vmCommands.join("\n")}`, LogLevel.DEBUG);
|
|
721
728
|
// Upload the post-startup commands script file.
|
|
722
|
-
|
|
729
|
+
printLog(`Uploading VM post-startup commands script file ${vmBootstrapScriptFilename}`, LogLevel.DEBUG);
|
|
730
|
+
await uploadFileToBucketNoFile(bucketName, `circuits/${circuit.name}/${vmBootstrapScriptFilename}`, vmCommands.join("\n"));
|
|
723
731
|
// Compute the VM disk space requirement (in GB).
|
|
724
732
|
const vmDiskSize = computeDiskSizeForVM(circuit.zKeySizeInBytes, circuit.metadata?.pot);
|
|
725
733
|
printLog(`Check VM startup commands ${startupCommand.join("\n")}`, LogLevel.DEBUG);
|
|
@@ -813,7 +821,7 @@ const finalizeCeremony = functions
|
|
|
813
821
|
// Get ceremony circuits.
|
|
814
822
|
const circuits = await getCeremonyCircuits(ceremonyId);
|
|
815
823
|
// Get final contribution for each circuit.
|
|
816
|
-
// nb. the `getFinalContributionDocument` checks the
|
|
824
|
+
// nb. the `getFinalContributionDocument` checks the existence of the final contribution document (if not present, throws).
|
|
817
825
|
// Therefore, we just need to call the method without taking any data to verify the pre-condition of having already computed
|
|
818
826
|
// the final contributions for each ceremony circuit.
|
|
819
827
|
for await (const circuit of circuits)
|
|
@@ -866,7 +874,7 @@ dotenv.config();
|
|
|
866
874
|
* @dev true when the participant can participate (1.A, 3.B, 1.D); otherwise false.
|
|
867
875
|
*/
|
|
868
876
|
const checkParticipantForCeremony = functions
|
|
869
|
-
.region(
|
|
877
|
+
.region("europe-west1")
|
|
870
878
|
.runWith({
|
|
871
879
|
memory: "512MB"
|
|
872
880
|
})
|
|
@@ -937,7 +945,7 @@ const checkParticipantForCeremony = functions
|
|
|
937
945
|
participantDoc.ref.update({
|
|
938
946
|
status: "EXHUMED" /* ParticipantStatus.EXHUMED */,
|
|
939
947
|
contributions,
|
|
940
|
-
tempContributionData: tempContributionData
|
|
948
|
+
tempContributionData: tempContributionData || FieldValue.delete(),
|
|
941
949
|
contributionStep: "DOWNLOADING" /* ParticipantContributionStep.DOWNLOADING */,
|
|
942
950
|
contributionStartedAt: 0,
|
|
943
951
|
verificationStartedAt: FieldValue.delete(),
|
|
@@ -970,7 +978,7 @@ const checkParticipantForCeremony = functions
|
|
|
970
978
|
* 2) the participant has just finished the contribution for a circuit (contributionProgress != 0 && status = CONTRIBUTED && contributionStep = COMPLETED).
|
|
971
979
|
*/
|
|
972
980
|
const progressToNextCircuitForContribution = functions
|
|
973
|
-
.region(
|
|
981
|
+
.region("europe-west1")
|
|
974
982
|
.runWith({
|
|
975
983
|
memory: "512MB"
|
|
976
984
|
})
|
|
@@ -1017,7 +1025,7 @@ const progressToNextCircuitForContribution = functions
|
|
|
1017
1025
|
* 5) Completed contribution computation and verification.
|
|
1018
1026
|
*/
|
|
1019
1027
|
const progressToNextContributionStep = functions
|
|
1020
|
-
.region(
|
|
1028
|
+
.region("europe-west1")
|
|
1021
1029
|
.runWith({
|
|
1022
1030
|
memory: "512MB"
|
|
1023
1031
|
})
|
|
@@ -1068,7 +1076,7 @@ const progressToNextContributionStep = functions
|
|
|
1068
1076
|
* @dev enable the current contributor to resume a contribution from where it had left off.
|
|
1069
1077
|
*/
|
|
1070
1078
|
const permanentlyStoreCurrentContributionTimeAndHash = functions
|
|
1071
|
-
.region(
|
|
1079
|
+
.region("europe-west1")
|
|
1072
1080
|
.runWith({
|
|
1073
1081
|
memory: "512MB"
|
|
1074
1082
|
})
|
|
@@ -1110,7 +1118,7 @@ const permanentlyStoreCurrentContributionTimeAndHash = functions
|
|
|
1110
1118
|
* @dev enable the current contributor to resume a multi-part upload from where it had left off.
|
|
1111
1119
|
*/
|
|
1112
1120
|
const temporaryStoreCurrentContributionMultiPartUploadId = functions
|
|
1113
|
-
.region(
|
|
1121
|
+
.region("europe-west1")
|
|
1114
1122
|
.runWith({
|
|
1115
1123
|
memory: "512MB"
|
|
1116
1124
|
})
|
|
@@ -1148,7 +1156,7 @@ const temporaryStoreCurrentContributionMultiPartUploadId = functions
|
|
|
1148
1156
|
* @dev enable the current contributor to resume a multi-part upload from where it had left off.
|
|
1149
1157
|
*/
|
|
1150
1158
|
const temporaryStoreCurrentContributionUploadedChunkData = functions
|
|
1151
|
-
.region(
|
|
1159
|
+
.region("europe-west1")
|
|
1152
1160
|
.runWith({
|
|
1153
1161
|
memory: "512MB"
|
|
1154
1162
|
})
|
|
@@ -1190,7 +1198,7 @@ const temporaryStoreCurrentContributionUploadedChunkData = functions
|
|
|
1190
1198
|
* contributed to every selected ceremony circuits (= DONE).
|
|
1191
1199
|
*/
|
|
1192
1200
|
const checkAndPrepareCoordinatorForFinalization = functions
|
|
1193
|
-
.region(
|
|
1201
|
+
.region("europe-west1")
|
|
1194
1202
|
.runWith({
|
|
1195
1203
|
memory: "512MB"
|
|
1196
1204
|
})
|
|
@@ -1342,54 +1350,74 @@ const coordinate = async (participant, circuit, isSingleParticipantCoordination,
|
|
|
1342
1350
|
* Wait until the command has completed its execution inside the VM.
|
|
1343
1351
|
* @dev this method implements a custom interval to check 5 times after 1 minute if the command execution
|
|
1344
1352
|
* has been completed or not by calling the `retrieveCommandStatus` method.
|
|
1345
|
-
* @param {any} resolve the promise.
|
|
1346
|
-
* @param {any} reject the promise.
|
|
1347
1353
|
* @param {SSMClient} ssm the SSM client.
|
|
1348
1354
|
* @param {string} vmInstanceId the unique identifier of the VM instance.
|
|
1349
1355
|
* @param {string} commandId the unique identifier of the VM command.
|
|
1350
1356
|
* @returns <Promise<void>> true when the command execution succeed; otherwise false.
|
|
1351
1357
|
*/
|
|
1352
|
-
const waitForVMCommandExecution = (
|
|
1353
|
-
const
|
|
1358
|
+
const waitForVMCommandExecution = (ssm, vmInstanceId, commandId) => new Promise((resolve, reject) => {
|
|
1359
|
+
const poll = async () => {
|
|
1354
1360
|
try {
|
|
1355
1361
|
// Get command status.
|
|
1356
1362
|
const cmdStatus = await retrieveCommandStatus(ssm, vmInstanceId, commandId);
|
|
1357
1363
|
printLog(`Checking command ${commandId} status => ${cmdStatus}`, LogLevel.DEBUG);
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1364
|
+
let error;
|
|
1365
|
+
switch (cmdStatus) {
|
|
1366
|
+
case CommandInvocationStatus.CANCELLING:
|
|
1367
|
+
case CommandInvocationStatus.CANCELLED: {
|
|
1368
|
+
error = SPECIFIC_ERRORS.SE_VM_CANCELLED_COMMAND_EXECUTION;
|
|
1369
|
+
break;
|
|
1370
|
+
}
|
|
1371
|
+
case CommandInvocationStatus.DELAYED: {
|
|
1372
|
+
error = SPECIFIC_ERRORS.SE_VM_DELAYED_COMMAND_EXECUTION;
|
|
1373
|
+
break;
|
|
1374
|
+
}
|
|
1375
|
+
case CommandInvocationStatus.FAILED: {
|
|
1376
|
+
error = SPECIFIC_ERRORS.SE_VM_FAILED_COMMAND_EXECUTION;
|
|
1377
|
+
break;
|
|
1378
|
+
}
|
|
1379
|
+
case CommandInvocationStatus.TIMED_OUT: {
|
|
1380
|
+
error = SPECIFIC_ERRORS.SE_VM_TIMEDOUT_COMMAND_EXECUTION;
|
|
1381
|
+
break;
|
|
1382
|
+
}
|
|
1383
|
+
case CommandInvocationStatus.IN_PROGRESS:
|
|
1384
|
+
case CommandInvocationStatus.PENDING: {
|
|
1385
|
+
// wait a minute and poll again
|
|
1386
|
+
setTimeout(poll, 60000);
|
|
1387
|
+
return;
|
|
1388
|
+
}
|
|
1389
|
+
case CommandInvocationStatus.SUCCESS: {
|
|
1390
|
+
printLog(`Command ${commandId} successfully completed`, LogLevel.DEBUG);
|
|
1391
|
+
// Resolve the promise.
|
|
1392
|
+
resolve();
|
|
1393
|
+
return;
|
|
1394
|
+
}
|
|
1395
|
+
default: {
|
|
1396
|
+
logAndThrowError(SPECIFIC_ERRORS.SE_VM_UNKNOWN_COMMAND_STATUS);
|
|
1397
|
+
}
|
|
1374
1398
|
}
|
|
1375
|
-
|
|
1376
|
-
logAndThrowError(
|
|
1377
|
-
reject();
|
|
1399
|
+
if (error) {
|
|
1400
|
+
logAndThrowError(error);
|
|
1378
1401
|
}
|
|
1379
1402
|
}
|
|
1380
1403
|
catch (error) {
|
|
1381
1404
|
printLog(`Invalid command ${commandId} execution`, LogLevel.DEBUG);
|
|
1405
|
+
const ec2 = await createEC2Client();
|
|
1406
|
+
// if it errors out, let's just log it as a warning so the coordinator is aware
|
|
1407
|
+
try {
|
|
1408
|
+
await stopEC2Instance(ec2, vmInstanceId);
|
|
1409
|
+
}
|
|
1410
|
+
catch (error) {
|
|
1411
|
+
printLog(`Error while stopping VM instance ${vmInstanceId} - Error ${error}`, LogLevel.WARN);
|
|
1412
|
+
}
|
|
1382
1413
|
if (!error.toString().includes(commandId))
|
|
1383
1414
|
logAndThrowError(COMMON_ERRORS.CM_INVALID_COMMAND_EXECUTION);
|
|
1384
1415
|
// Reject the promise.
|
|
1385
1416
|
reject();
|
|
1386
1417
|
}
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
}
|
|
1391
|
-
}, 60000); // 1 minute.
|
|
1392
|
-
};
|
|
1418
|
+
};
|
|
1419
|
+
setTimeout(poll, 60000);
|
|
1420
|
+
});
|
|
1393
1421
|
/**
|
|
1394
1422
|
* This method is used to coordinate the waiting queues of ceremony circuits.
|
|
1395
1423
|
* @dev this cloud function is triggered whenever an update of a document related to a participant of a ceremony occurs.
|
|
@@ -1410,7 +1438,7 @@ const waitForVMCommandExecution = (resolve, reject, ssm, vmInstanceId, commandId
|
|
|
1410
1438
|
* - Just completed a contribution or all contributions for each circuit. If yes, coordinate (multi-participant scenario).
|
|
1411
1439
|
*/
|
|
1412
1440
|
const coordinateCeremonyParticipant = functionsV1
|
|
1413
|
-
.region(
|
|
1441
|
+
.region("europe-west1")
|
|
1414
1442
|
.runWith({
|
|
1415
1443
|
memory: "512MB"
|
|
1416
1444
|
})
|
|
@@ -1481,11 +1509,9 @@ const checkIfVMRunning = async (ec2, vmInstanceId, attempts = 5) => {
|
|
|
1481
1509
|
const isVMRunning = await checkIfRunning(ec2, vmInstanceId);
|
|
1482
1510
|
if (!isVMRunning) {
|
|
1483
1511
|
printLog(`VM not running, ${attempts - 1} attempts remaining. Retrying in 1 minute...`, LogLevel.DEBUG);
|
|
1484
|
-
return
|
|
1485
|
-
}
|
|
1486
|
-
else {
|
|
1487
|
-
return true;
|
|
1512
|
+
return checkIfVMRunning(ec2, vmInstanceId, attempts - 1);
|
|
1488
1513
|
}
|
|
1514
|
+
return true;
|
|
1489
1515
|
};
|
|
1490
1516
|
/**
|
|
1491
1517
|
* Verify the contribution of a participant computed while contributing to a specific circuit of a ceremony.
|
|
@@ -1513,7 +1539,7 @@ const checkIfVMRunning = async (ec2, vmInstanceId, attempts = 5) => {
|
|
|
1513
1539
|
* 1.A.4.C.1) If true, update circuit waiting for queue and average timings accordingly to contribution verification results;
|
|
1514
1540
|
* 2) Send all updates atomically to the Firestore database.
|
|
1515
1541
|
*/
|
|
1516
|
-
const verifycontribution = functionsV2.https.onCall({ memory: "16GiB", timeoutSeconds: 3600, region:
|
|
1542
|
+
const verifycontribution = functionsV2.https.onCall({ memory: "16GiB", timeoutSeconds: 3600, region: "europe-west1" }, async (request) => {
|
|
1517
1543
|
if (!request.auth || (!request.auth.token.participant && !request.auth.token.coordinator))
|
|
1518
1544
|
logAndThrowError(SPECIFIC_ERRORS.SE_AUTH_NO_CURRENT_AUTH_USER);
|
|
1519
1545
|
if (!request.data.ceremonyId ||
|
|
@@ -1624,8 +1650,6 @@ const verifycontribution = functionsV2.https.onCall({ memory: "16GiB", timeoutSe
|
|
|
1624
1650
|
lastZkeyBlake2bHash = match.at(0);
|
|
1625
1651
|
// re upload the formatted verification transcript
|
|
1626
1652
|
await uploadFileToBucket(bucketName, verificationTranscriptStoragePathAndFilename, verificationTranscriptTemporaryLocalPath, true);
|
|
1627
|
-
// Stop VM instance.
|
|
1628
|
-
await stopEC2Instance(ec2, vmInstanceId);
|
|
1629
1653
|
}
|
|
1630
1654
|
else {
|
|
1631
1655
|
// Upload verification transcript.
|
|
@@ -1686,6 +1710,18 @@ const verifycontribution = functionsV2.https.onCall({ memory: "16GiB", timeoutSe
|
|
|
1686
1710
|
lastUpdated: getCurrentServerTimestampInMillis()
|
|
1687
1711
|
});
|
|
1688
1712
|
}
|
|
1713
|
+
// Stop VM instance
|
|
1714
|
+
if (isUsingVM) {
|
|
1715
|
+
// using try and catch as the VM stopping function can throw
|
|
1716
|
+
// however we want to continue without stopping as the
|
|
1717
|
+
// verification was valid, and inform the coordinator
|
|
1718
|
+
try {
|
|
1719
|
+
await stopEC2Instance(ec2, vmInstanceId);
|
|
1720
|
+
}
|
|
1721
|
+
catch (error) {
|
|
1722
|
+
printLog(`Error while stopping VM instance ${vmInstanceId} - Error ${error}`, LogLevel.WARN);
|
|
1723
|
+
}
|
|
1724
|
+
}
|
|
1689
1725
|
// Step (1.A.4.C)
|
|
1690
1726
|
if (!isFinalizing) {
|
|
1691
1727
|
// Step (1.A.4.C.1)
|
|
@@ -1700,7 +1736,7 @@ const verifycontribution = functionsV2.https.onCall({ memory: "16GiB", timeoutSe
|
|
|
1700
1736
|
const newAvgVerifyCloudFunctionTime = avgVerifyCloudFunctionTime > 0
|
|
1701
1737
|
? (avgVerifyCloudFunctionTime + verifyCloudFunctionTime) / 2
|
|
1702
1738
|
: verifyCloudFunctionTime;
|
|
1703
|
-
// Prepare tx to update circuit average contribution/verification time.
|
|
1739
|
+
// Prepare tx to update circuit average contribution/verification time.
|
|
1704
1740
|
const updatedCircuitDoc = await getDocumentById(getCircuitsCollectionPath(ceremonyId), circuitId);
|
|
1705
1741
|
const { waitingQueue: updatedWaitingQueue } = updatedCircuitDoc.data();
|
|
1706
1742
|
/// @dev this must happen only for valid contributions.
|
|
@@ -1750,7 +1786,7 @@ const verifycontribution = functionsV2.https.onCall({ memory: "16GiB", timeoutSe
|
|
|
1750
1786
|
commandId = await runCommandUsingSSM(ssm, vmInstanceId, verificationCommand);
|
|
1751
1787
|
printLog(`Starting the execution of command ${commandId}`, LogLevel.DEBUG);
|
|
1752
1788
|
// Step (1.A.3.3).
|
|
1753
|
-
return
|
|
1789
|
+
return waitForVMCommandExecution(ssm, vmInstanceId, commandId)
|
|
1754
1790
|
.then(async () => {
|
|
1755
1791
|
// Command execution successfully completed.
|
|
1756
1792
|
printLog(`Command ${commandId} execution has been successfully completed`, LogLevel.DEBUG);
|
|
@@ -1762,40 +1798,38 @@ const verifycontribution = functionsV2.https.onCall({ memory: "16GiB", timeoutSe
|
|
|
1762
1798
|
logAndThrowError(COMMON_ERRORS.CM_INVALID_COMMAND_EXECUTION);
|
|
1763
1799
|
});
|
|
1764
1800
|
}
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
printLog(`Error while unlinking temporary files - Error ${error}`, LogLevel.WARN);
|
|
1796
|
-
}
|
|
1797
|
-
await completeVerification();
|
|
1801
|
+
// CF approach.
|
|
1802
|
+
printLog(`CF mechanism`, LogLevel.DEBUG);
|
|
1803
|
+
const potStoragePath = getPotStorageFilePath(files.potFilename);
|
|
1804
|
+
const firstZkeyStoragePath = getZkeyStorageFilePath(prefix, `${prefix}_${genesisZkeyIndex}.zkey`);
|
|
1805
|
+
// Prepare temporary file paths.
|
|
1806
|
+
// (nb. these are needed to download the necessary artifacts for verification from AWS S3).
|
|
1807
|
+
verificationTranscriptTemporaryLocalPath = createTemporaryLocalPath(verificationTranscriptCompleteFilename);
|
|
1808
|
+
const potTempFilePath = createTemporaryLocalPath(`${circuitId}_${participantDoc.id}.pot`);
|
|
1809
|
+
const firstZkeyTempFilePath = createTemporaryLocalPath(`${circuitId}_${participantDoc.id}_genesis.zkey`);
|
|
1810
|
+
const lastZkeyTempFilePath = createTemporaryLocalPath(`${circuitId}_${participantDoc.id}_last.zkey`);
|
|
1811
|
+
// Create and populate transcript.
|
|
1812
|
+
const transcriptLogger = createCustomLoggerForFile(verificationTranscriptTemporaryLocalPath);
|
|
1813
|
+
transcriptLogger.info(`${isFinalizing ? `Final verification` : `Verification`} transcript for ${prefix} circuit Phase 2 contribution.\n${isFinalizing ? `Coordinator ` : `Contributor # ${Number(lastZkeyIndex)}`} (${contributorOrCoordinatorIdentifier})\n`);
|
|
1814
|
+
// Step (1.A.2).
|
|
1815
|
+
await downloadArtifactFromS3Bucket(bucketName, potStoragePath, potTempFilePath);
|
|
1816
|
+
await downloadArtifactFromS3Bucket(bucketName, firstZkeyStoragePath, firstZkeyTempFilePath);
|
|
1817
|
+
await downloadArtifactFromS3Bucket(bucketName, lastZkeyStoragePath, lastZkeyTempFilePath);
|
|
1818
|
+
// Step (1.A.4).
|
|
1819
|
+
isContributionValid = await zKey.verifyFromInit(firstZkeyTempFilePath, potTempFilePath, lastZkeyTempFilePath, transcriptLogger);
|
|
1820
|
+
// Compute contribution hash.
|
|
1821
|
+
lastZkeyBlake2bHash = await blake512FromPath(lastZkeyTempFilePath);
|
|
1822
|
+
// Free resources by unlinking temporary folders.
|
|
1823
|
+
// Do not free-up verification transcript path here.
|
|
1824
|
+
try {
|
|
1825
|
+
fs.unlinkSync(potTempFilePath);
|
|
1826
|
+
fs.unlinkSync(firstZkeyTempFilePath);
|
|
1827
|
+
fs.unlinkSync(lastZkeyTempFilePath);
|
|
1828
|
+
}
|
|
1829
|
+
catch (error) {
|
|
1830
|
+
printLog(`Error while unlinking temporary files - Error ${error}`, LogLevel.WARN);
|
|
1798
1831
|
}
|
|
1832
|
+
await completeVerification();
|
|
1799
1833
|
}
|
|
1800
1834
|
});
|
|
1801
1835
|
/**
|
|
@@ -1804,7 +1838,7 @@ const verifycontribution = functionsV2.https.onCall({ memory: "16GiB", timeoutSe
|
|
|
1804
1838
|
* this does not happen if the participant is actually the coordinator who is finalizing the ceremony.
|
|
1805
1839
|
*/
|
|
1806
1840
|
const refreshParticipantAfterContributionVerification = functionsV1
|
|
1807
|
-
.region(
|
|
1841
|
+
.region("europe-west1")
|
|
1808
1842
|
.runWith({
|
|
1809
1843
|
memory: "512MB"
|
|
1810
1844
|
})
|
|
@@ -1865,7 +1899,7 @@ const refreshParticipantAfterContributionVerification = functionsV1
|
|
|
1865
1899
|
* and verification key extracted from the circuit final contribution (as part of the ceremony finalization process).
|
|
1866
1900
|
*/
|
|
1867
1901
|
const finalizeCircuit = functionsV1
|
|
1868
|
-
.region(
|
|
1902
|
+
.region("europe-west1")
|
|
1869
1903
|
.runWith({
|
|
1870
1904
|
memory: "512MB"
|
|
1871
1905
|
})
|
|
@@ -2062,8 +2096,10 @@ const createBucket = functions
|
|
|
2062
2096
|
CORSConfiguration: {
|
|
2063
2097
|
CORSRules: [
|
|
2064
2098
|
{
|
|
2065
|
-
AllowedMethods: ["GET"],
|
|
2066
|
-
AllowedOrigins: ["*"]
|
|
2099
|
+
AllowedMethods: ["GET", "PUT"],
|
|
2100
|
+
AllowedOrigins: ["*"],
|
|
2101
|
+
ExposeHeaders: ["ETag", "Content-Length"],
|
|
2102
|
+
AllowedHeaders: ["*"]
|
|
2067
2103
|
}
|
|
2068
2104
|
]
|
|
2069
2105
|
}
|
|
@@ -2240,7 +2276,8 @@ const startMultiPartUpload = functions
|
|
|
2240
2276
|
const generatePreSignedUrlsParts = functions
|
|
2241
2277
|
.region("europe-west1")
|
|
2242
2278
|
.runWith({
|
|
2243
|
-
memory: "512MB"
|
|
2279
|
+
memory: "512MB",
|
|
2280
|
+
timeoutSeconds: 300
|
|
2244
2281
|
})
|
|
2245
2282
|
.https.onCall(async (data, context) => {
|
|
2246
2283
|
if (!context.auth || (!context.auth.token.participant && !context.auth.token.coordinator))
|
|
@@ -2349,6 +2386,148 @@ const completeMultiPartUpload = functions
|
|
|
2349
2386
|
}
|
|
2350
2387
|
});
|
|
2351
2388
|
|
|
2389
|
+
const VKEY_DATA = {
|
|
2390
|
+
protocol: "groth16",
|
|
2391
|
+
curve: "bn128",
|
|
2392
|
+
nPublic: 3,
|
|
2393
|
+
vk_alpha_1: [
|
|
2394
|
+
"20491192805390485299153009773594534940189261866228447918068658471970481763042",
|
|
2395
|
+
"9383485363053290200918347156157836566562967994039712273449902621266178545958",
|
|
2396
|
+
"1"
|
|
2397
|
+
],
|
|
2398
|
+
vk_beta_2: [
|
|
2399
|
+
[
|
|
2400
|
+
"6375614351688725206403948262868962793625744043794305715222011528459656738731",
|
|
2401
|
+
"4252822878758300859123897981450591353533073413197771768651442665752259397132"
|
|
2402
|
+
],
|
|
2403
|
+
[
|
|
2404
|
+
"10505242626370262277552901082094356697409835680220590971873171140371331206856",
|
|
2405
|
+
"21847035105528745403288232691147584728191162732299865338377159692350059136679"
|
|
2406
|
+
],
|
|
2407
|
+
["1", "0"]
|
|
2408
|
+
],
|
|
2409
|
+
vk_gamma_2: [
|
|
2410
|
+
[
|
|
2411
|
+
"10857046999023057135944570762232829481370756359578518086990519993285655852781",
|
|
2412
|
+
"11559732032986387107991004021392285783925812861821192530917403151452391805634"
|
|
2413
|
+
],
|
|
2414
|
+
[
|
|
2415
|
+
"8495653923123431417604973247489272438418190587263600148770280649306958101930",
|
|
2416
|
+
"4082367875863433681332203403145435568316851327593401208105741076214120093531"
|
|
2417
|
+
],
|
|
2418
|
+
["1", "0"]
|
|
2419
|
+
],
|
|
2420
|
+
vk_delta_2: [
|
|
2421
|
+
[
|
|
2422
|
+
"3697618915467790705869942236922063775466274665053173890632463796679068973252",
|
|
2423
|
+
"14948341351907992175709156460547989243732741534604949238422596319735704165658"
|
|
2424
|
+
],
|
|
2425
|
+
[
|
|
2426
|
+
"3028459181652799888716942141752307629938889957960373621898607910203491239368",
|
|
2427
|
+
"11380736494786911280692284374675752681598754560757720296073023058533044108340"
|
|
2428
|
+
],
|
|
2429
|
+
["1", "0"]
|
|
2430
|
+
],
|
|
2431
|
+
vk_alphabeta_12: [
|
|
2432
|
+
[
|
|
2433
|
+
[
|
|
2434
|
+
"2029413683389138792403550203267699914886160938906632433982220835551125967885",
|
|
2435
|
+
"21072700047562757817161031222997517981543347628379360635925549008442030252106"
|
|
2436
|
+
],
|
|
2437
|
+
[
|
|
2438
|
+
"5940354580057074848093997050200682056184807770593307860589430076672439820312",
|
|
2439
|
+
"12156638873931618554171829126792193045421052652279363021382169897324752428276"
|
|
2440
|
+
],
|
|
2441
|
+
[
|
|
2442
|
+
"7898200236362823042373859371574133993780991612861777490112507062703164551277",
|
|
2443
|
+
"7074218545237549455313236346927434013100842096812539264420499035217050630853"
|
|
2444
|
+
]
|
|
2445
|
+
],
|
|
2446
|
+
[
|
|
2447
|
+
[
|
|
2448
|
+
"7077479683546002997211712695946002074877511277312570035766170199895071832130",
|
|
2449
|
+
"10093483419865920389913245021038182291233451549023025229112148274109565435465"
|
|
2450
|
+
],
|
|
2451
|
+
[
|
|
2452
|
+
"4595479056700221319381530156280926371456704509942304414423590385166031118820",
|
|
2453
|
+
"19831328484489333784475432780421641293929726139240675179672856274388269393268"
|
|
2454
|
+
],
|
|
2455
|
+
[
|
|
2456
|
+
"11934129596455521040620786944827826205713621633706285934057045369193958244500",
|
|
2457
|
+
"8037395052364110730298837004334506829870972346962140206007064471173334027475"
|
|
2458
|
+
]
|
|
2459
|
+
]
|
|
2460
|
+
],
|
|
2461
|
+
IC: [
|
|
2462
|
+
[
|
|
2463
|
+
"12951059800758687233303204819298121944551181861362200875212570257618182506154",
|
|
2464
|
+
"5751958719396509176593242305268064754837298673622815112953832050159760501392",
|
|
2465
|
+
"1"
|
|
2466
|
+
],
|
|
2467
|
+
[
|
|
2468
|
+
"9561588427935871983444704959674198910445823619407211599507208879011862515257",
|
|
2469
|
+
"14576201570478094842467636169770180675293504492823217349086195663150934064643",
|
|
2470
|
+
"1"
|
|
2471
|
+
],
|
|
2472
|
+
[
|
|
2473
|
+
"4811967233483727873912563574622036989372099129165459921963463310078093941559",
|
|
2474
|
+
"1874883809855039536107616044787862082553628089593740724610117059083415551067",
|
|
2475
|
+
"1"
|
|
2476
|
+
],
|
|
2477
|
+
[
|
|
2478
|
+
"12252730267779308452229639835051322390696643456253768618882001876621526827161",
|
|
2479
|
+
"7899194018737016222260328309937800777948677569409898603827268776967707173231",
|
|
2480
|
+
"1"
|
|
2481
|
+
]
|
|
2482
|
+
]
|
|
2483
|
+
};
|
|
2484
|
+
dotenv.config();
|
|
2485
|
+
const { BANDADA_API_URL, BANDADA_GROUP_ID } = process.env;
|
|
2486
|
+
const bandadaApi = new ApiSdk(BANDADA_API_URL);
|
|
2487
|
+
const bandadaValidateProof = functions
|
|
2488
|
+
.region("europe-west1")
|
|
2489
|
+
.runWith({
|
|
2490
|
+
memory: "512MB"
|
|
2491
|
+
})
|
|
2492
|
+
.https.onCall(async (data) => {
|
|
2493
|
+
if (!BANDADA_GROUP_ID)
|
|
2494
|
+
throw new Error("BANDADA_GROUP_ID is not defined in .env");
|
|
2495
|
+
const { proof, publicSignals } = data;
|
|
2496
|
+
const isCorrect = groth16.verify(VKEY_DATA, publicSignals, proof);
|
|
2497
|
+
if (!isCorrect)
|
|
2498
|
+
return {
|
|
2499
|
+
valid: false,
|
|
2500
|
+
message: "Invalid proof",
|
|
2501
|
+
token: ""
|
|
2502
|
+
};
|
|
2503
|
+
const commitment = data.publicSignals[1];
|
|
2504
|
+
const isMember = await bandadaApi.isGroupMember(BANDADA_GROUP_ID, commitment);
|
|
2505
|
+
if (!isMember)
|
|
2506
|
+
return {
|
|
2507
|
+
valid: false,
|
|
2508
|
+
message: "Not a member of the group",
|
|
2509
|
+
token: ""
|
|
2510
|
+
};
|
|
2511
|
+
const auth = getAuth();
|
|
2512
|
+
try {
|
|
2513
|
+
await admin.auth().createUser({
|
|
2514
|
+
uid: commitment
|
|
2515
|
+
});
|
|
2516
|
+
}
|
|
2517
|
+
catch (error) {
|
|
2518
|
+
// if user already exist then just pass
|
|
2519
|
+
if (error.code !== "auth/uid-already-exists") {
|
|
2520
|
+
throw new Error(error);
|
|
2521
|
+
}
|
|
2522
|
+
}
|
|
2523
|
+
const token = await auth.createCustomToken(commitment);
|
|
2524
|
+
return {
|
|
2525
|
+
valid: true,
|
|
2526
|
+
message: "Valid proof and group member",
|
|
2527
|
+
token
|
|
2528
|
+
};
|
|
2529
|
+
});
|
|
2530
|
+
|
|
2352
2531
|
dotenv.config();
|
|
2353
2532
|
/**
|
|
2354
2533
|
* Check and remove the current contributor if it doesn't complete the contribution on the specified amount of time.
|
|
@@ -2390,7 +2569,7 @@ const checkAndRemoveBlockingContributor = functions
|
|
|
2390
2569
|
// Get ceremony circuits.
|
|
2391
2570
|
const circuits = await getCeremonyCircuits(ceremony.id);
|
|
2392
2571
|
// Extract ceremony data.
|
|
2393
|
-
const { timeoutMechanismType, penalty } = ceremony.data();
|
|
2572
|
+
const { timeoutType: timeoutMechanismType, penalty } = ceremony.data();
|
|
2394
2573
|
for (const circuit of circuits) {
|
|
2395
2574
|
if (!circuit.data())
|
|
2396
2575
|
// Do not use `logAndThrowError` method to avoid the function to exit before checking every ceremony.
|
|
@@ -2540,7 +2719,8 @@ const resumeContributionAfterTimeoutExpiration = functions
|
|
|
2540
2719
|
if (status === "EXHUMED" /* ParticipantStatus.EXHUMED */)
|
|
2541
2720
|
await participantDoc.ref.update({
|
|
2542
2721
|
status: "READY" /* ParticipantStatus.READY */,
|
|
2543
|
-
lastUpdated: getCurrentServerTimestampInMillis()
|
|
2722
|
+
lastUpdated: getCurrentServerTimestampInMillis(),
|
|
2723
|
+
tempContributionData: {}
|
|
2544
2724
|
});
|
|
2545
2725
|
else
|
|
2546
2726
|
logAndThrowError(SPECIFIC_ERRORS.SE_CONTRIBUTE_CANNOT_PROGRESS_TO_NEXT_CIRCUIT);
|
|
@@ -2549,4 +2729,4 @@ const resumeContributionAfterTimeoutExpiration = functions
|
|
|
2549
2729
|
|
|
2550
2730
|
admin.initializeApp();
|
|
2551
2731
|
|
|
2552
|
-
export { checkAndPrepareCoordinatorForFinalization, checkAndRemoveBlockingContributor, checkIfObjectExist, checkParticipantForCeremony, completeMultiPartUpload, coordinateCeremonyParticipant, createBucket, finalizeCeremony, finalizeCircuit, generateGetObjectPreSignedUrl, generatePreSignedUrlsParts, initEmptyWaitingQueueForCircuit, permanentlyStoreCurrentContributionTimeAndHash, processSignUpWithCustomClaims, progressToNextCircuitForContribution, progressToNextContributionStep, refreshParticipantAfterContributionVerification, registerAuthUser, resumeContributionAfterTimeoutExpiration, setupCeremony, startCeremony, startMultiPartUpload, stopCeremony, temporaryStoreCurrentContributionMultiPartUploadId, temporaryStoreCurrentContributionUploadedChunkData, verifycontribution };
|
|
2732
|
+
export { bandadaValidateProof, checkAndPrepareCoordinatorForFinalization, checkAndRemoveBlockingContributor, checkIfObjectExist, checkParticipantForCeremony, completeMultiPartUpload, coordinateCeremonyParticipant, createBucket, finalizeCeremony, finalizeCircuit, generateGetObjectPreSignedUrl, generatePreSignedUrlsParts, initEmptyWaitingQueueForCircuit, permanentlyStoreCurrentContributionTimeAndHash, processSignUpWithCustomClaims, progressToNextCircuitForContribution, progressToNextContributionStep, refreshParticipantAfterContributionVerification, registerAuthUser, resumeContributionAfterTimeoutExpiration, setupCeremony, startCeremony, startMultiPartUpload, stopCeremony, temporaryStoreCurrentContributionMultiPartUploadId, temporaryStoreCurrentContributionUploadedChunkData, verifycontribution };
|