@devtion/backend 0.0.0-3df1645 → 0.0.0-477457c
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 +2 -2
- package/dist/src/functions/index.js +627 -345
- package/dist/src/functions/index.mjs +628 -348
- package/dist/src/functions/types/functions/bandada.d.ts +4 -0
- package/dist/src/functions/types/functions/bandada.d.ts.map +1 -0
- package/dist/{types → src/functions/types}/functions/ceremony.d.ts.map +1 -1
- package/dist/{types → src/functions/types}/functions/circuit.d.ts.map +1 -1
- package/dist/{types → src/functions/types}/functions/index.d.ts +2 -0
- package/dist/{types → src/functions/types}/functions/index.d.ts.map +1 -1
- package/dist/src/functions/types/functions/siwe.d.ts +4 -0
- package/dist/src/functions/types/functions/siwe.d.ts.map +1 -0
- package/dist/{types → src/functions/types}/functions/storage.d.ts.map +1 -1
- package/dist/{types → src/functions/types}/functions/timeout.d.ts.map +1 -1
- package/dist/{types → src/functions/types}/functions/user.d.ts.map +1 -1
- package/dist/{types → src/functions/types}/lib/errors.d.ts +2 -1
- package/dist/src/functions/types/lib/errors.d.ts.map +1 -0
- package/dist/{types → src/functions/types}/lib/services.d.ts +7 -0
- package/dist/src/functions/types/lib/services.d.ts.map +1 -0
- package/dist/src/functions/types/lib/utils.d.ts.map +1 -0
- package/dist/{types → src/functions/types}/types/index.d.ts +56 -0
- package/dist/src/functions/types/types/index.d.ts.map +1 -0
- package/package.json +8 -7
- package/src/functions/bandada.ts +154 -0
- package/src/functions/ceremony.ts +11 -7
- package/src/functions/circuit.ts +414 -384
- package/src/functions/index.ts +2 -0
- package/src/functions/participant.ts +8 -8
- package/src/functions/siwe.ts +77 -0
- package/src/functions/storage.ts +7 -6
- package/src/functions/timeout.ts +14 -13
- package/src/functions/user.ts +6 -5
- package/src/lib/errors.ts +6 -1
- package/src/lib/services.ts +36 -0
- package/src/lib/utils.ts +8 -6
- package/src/types/declarations.d.ts +1 -0
- package/src/types/index.ts +60 -0
- package/dist/types/lib/errors.d.ts.map +0 -1
- package/dist/types/lib/services.d.ts.map +0 -1
- package/dist/types/lib/utils.d.ts.map +0 -1
- package/dist/types/types/index.d.ts.map +0 -1
- /package/dist/{types → src/functions/types}/functions/ceremony.d.ts +0 -0
- /package/dist/{types → src/functions/types}/functions/circuit.d.ts +0 -0
- /package/dist/{types → src/functions/types}/functions/participant.d.ts +0 -0
- /package/dist/{types → src/functions/types}/functions/participant.d.ts.map +0 -0
- /package/dist/{types → src/functions/types}/functions/storage.d.ts +0 -0
- /package/dist/{types → src/functions/types}/functions/timeout.d.ts +0 -0
- /package/dist/{types → src/functions/types}/functions/user.d.ts +0 -0
- /package/dist/{types → src/functions/types}/lib/utils.d.ts +0 -0
- /package/dist/{types → src/functions/types}/types/enums.d.ts +0 -0
- /package/dist/{types → src/functions/types}/types/enums.d.ts.map +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module @p0tion/backend
|
|
3
|
-
* @version 1.
|
|
3
|
+
* @version 1.2.8
|
|
4
4
|
* @file MPC Phase 2 backend for Firebase services management
|
|
5
5
|
* @copyright Ethereum Foundation 2022
|
|
6
6
|
* @license MIT
|
|
@@ -27,10 +27,13 @@ var path = require('path');
|
|
|
27
27
|
var os = require('os');
|
|
28
28
|
var clientSsm = require('@aws-sdk/client-ssm');
|
|
29
29
|
var clientEc2 = require('@aws-sdk/client-ec2');
|
|
30
|
+
var ethers = require('ethers');
|
|
30
31
|
var functionsV1 = require('firebase-functions/v1');
|
|
31
32
|
var functionsV2 = require('firebase-functions/v2');
|
|
32
33
|
var timerNode = require('timer-node');
|
|
33
34
|
var snarkjs = require('snarkjs');
|
|
35
|
+
var apiSdk = require('@bandada/api-sdk');
|
|
36
|
+
var auth = require('firebase-admin/auth');
|
|
34
37
|
|
|
35
38
|
function _interopNamespaceDefault(e) {
|
|
36
39
|
var n = Object.create(null);
|
|
@@ -72,7 +75,7 @@ var LogLevel;
|
|
|
72
75
|
* @notice the set of Firebase Functions status codes. The codes are the same at the
|
|
73
76
|
* ones exposed by {@link https://github.com/grpc/grpc/blob/master/doc/statuscodes.md | gRPC}.
|
|
74
77
|
* @param errorCode <FunctionsErrorCode> - the set of possible error codes.
|
|
75
|
-
* @param message <string> - the error
|
|
78
|
+
* @param message <string> - the error message.
|
|
76
79
|
* @param [details] <string> - the details of the error (optional).
|
|
77
80
|
* @returns <HttpsError>
|
|
78
81
|
*/
|
|
@@ -145,7 +148,8 @@ const SPECIFIC_ERRORS = {
|
|
|
145
148
|
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."),
|
|
146
149
|
SE_VM_CANCELLED_COMMAND_EXECUTION: makeError("cancelled", "VM command execution has been cancelled", "Please, contact the coordinator if this error persists."),
|
|
147
150
|
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."),
|
|
148
|
-
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.")
|
|
151
|
+
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."),
|
|
152
|
+
WRONG_BUCKET_NAME: makeError("invalid-argument", "The provided bucket name is not valid.", "Bucket names must be between 3 and 63 characters long, can only contain lowercase letters, numbers, and hyphens, and must start and end with a letter or number.")
|
|
149
153
|
};
|
|
150
154
|
/**
|
|
151
155
|
* A set of common errors.
|
|
@@ -164,6 +168,8 @@ const COMMON_ERRORS = {
|
|
|
164
168
|
CM_INVALID_COMMAND_EXECUTION: makeError("unknown", "There was an error while executing the command on the VM", "Please, contact the coordinator if the error persists.")
|
|
165
169
|
};
|
|
166
170
|
|
|
171
|
+
dotenv.config();
|
|
172
|
+
let provider;
|
|
167
173
|
/**
|
|
168
174
|
* Return a configured and connected instance of the AWS S3 client.
|
|
169
175
|
* @dev this method check and utilize the environment variables to configure the connection
|
|
@@ -186,6 +192,36 @@ const getS3Client = async () => {
|
|
|
186
192
|
region: process.env.AWS_REGION
|
|
187
193
|
});
|
|
188
194
|
};
|
|
195
|
+
/**
|
|
196
|
+
* Returns a Prvider, connected via a configured JSON URL or else
|
|
197
|
+
* the ethers.js default provider, using configured API keys.
|
|
198
|
+
* @returns <ethers.providers.Provider> An Eth node provider
|
|
199
|
+
*/
|
|
200
|
+
const setEthProvider = () => {
|
|
201
|
+
if (provider)
|
|
202
|
+
return provider;
|
|
203
|
+
console.log(`setting new provider`);
|
|
204
|
+
// Use JSON URL if defined
|
|
205
|
+
// if ((hardhat as any).ethers) {
|
|
206
|
+
// console.log(`using hardhat.ethers provider`)
|
|
207
|
+
// provider = (hardhat as any).ethers.provider
|
|
208
|
+
// } else
|
|
209
|
+
if (process.env.ETH_PROVIDER_JSON_URL) {
|
|
210
|
+
console.log(`JSON URL provider at ${process.env.ETH_PROVIDER_JSON_URL}`);
|
|
211
|
+
provider = new ethers.providers.JsonRpcProvider({
|
|
212
|
+
url: process.env.ETH_PROVIDER_JSON_URL,
|
|
213
|
+
skipFetchSetup: true
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
// Otherwise, connect the default provider with ALchemy, Infura, or both
|
|
218
|
+
provider = ethers.providers.getDefaultProvider("homestead", {
|
|
219
|
+
alchemy: process.env.ETH_PROVIDER_ALCHEMY_API_KEY,
|
|
220
|
+
infura: process.env.ETH_PROVIDER_INFURA_API_KEY
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
return provider;
|
|
224
|
+
};
|
|
189
225
|
|
|
190
226
|
dotenv.config();
|
|
191
227
|
/**
|
|
@@ -288,7 +324,7 @@ const queryOpenedCeremonies = async () => {
|
|
|
288
324
|
const getCircuitDocumentByPosition = async (ceremonyId, sequencePosition) => {
|
|
289
325
|
// Query for all ceremony circuits.
|
|
290
326
|
const circuits = await getCeremonyCircuits(ceremonyId);
|
|
291
|
-
// Apply a filter using the sequence
|
|
327
|
+
// Apply a filter using the sequence position.
|
|
292
328
|
const matchedCircuits = circuits.filter((circuit) => circuit.data().sequencePosition === sequencePosition);
|
|
293
329
|
if (matchedCircuits.length !== 1)
|
|
294
330
|
logAndThrowError(COMMON_ERRORS.CM_NO_CIRCUIT_FOR_GIVEN_SEQUENCE_POSITION);
|
|
@@ -453,12 +489,14 @@ const htmlEncodeCircuitData = (circuitDocument) => ({
|
|
|
453
489
|
const getGitHubVariables = () => {
|
|
454
490
|
if (!process.env.GITHUB_MINIMUM_FOLLOWERS ||
|
|
455
491
|
!process.env.GITHUB_MINIMUM_FOLLOWING ||
|
|
456
|
-
!process.env.GITHUB_MINIMUM_PUBLIC_REPOS
|
|
492
|
+
!process.env.GITHUB_MINIMUM_PUBLIC_REPOS ||
|
|
493
|
+
!process.env.GITHUB_MINIMUM_AGE)
|
|
457
494
|
logAndThrowError(COMMON_ERRORS.CM_WRONG_CONFIGURATION);
|
|
458
495
|
return {
|
|
459
496
|
minimumFollowers: Number(process.env.GITHUB_MINIMUM_FOLLOWERS),
|
|
460
497
|
minimumFollowing: Number(process.env.GITHUB_MINIMUM_FOLLOWING),
|
|
461
|
-
minimumPublicRepos: Number(process.env.GITHUB_MINIMUM_PUBLIC_REPOS)
|
|
498
|
+
minimumPublicRepos: Number(process.env.GITHUB_MINIMUM_PUBLIC_REPOS),
|
|
499
|
+
minimumAge: Number(process.env.GITHUB_MINIMUM_AGE)
|
|
462
500
|
};
|
|
463
501
|
};
|
|
464
502
|
/**
|
|
@@ -468,7 +506,7 @@ const getGitHubVariables = () => {
|
|
|
468
506
|
const getAWSVariables = () => {
|
|
469
507
|
if (!process.env.AWS_ACCESS_KEY_ID ||
|
|
470
508
|
!process.env.AWS_SECRET_ACCESS_KEY ||
|
|
471
|
-
!process.env.
|
|
509
|
+
!process.env.AWS_INSTANCE_PROFILE_ARN ||
|
|
472
510
|
!process.env.AWS_AMI_ID ||
|
|
473
511
|
!process.env.AWS_SNS_TOPIC_ARN)
|
|
474
512
|
logAndThrowError(COMMON_ERRORS.CM_WRONG_CONFIGURATION);
|
|
@@ -476,7 +514,7 @@ const getAWSVariables = () => {
|
|
|
476
514
|
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
|
|
477
515
|
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
|
|
478
516
|
region: process.env.AWS_REGION || "eu-central-1",
|
|
479
|
-
|
|
517
|
+
instanceProfileArn: process.env.AWS_INSTANCE_PROFILE_ARN,
|
|
480
518
|
amiId: process.env.AWS_AMI_ID,
|
|
481
519
|
snsTopic: process.env.AWS_SNS_TOPIC_ARN
|
|
482
520
|
};
|
|
@@ -522,7 +560,7 @@ dotenv.config();
|
|
|
522
560
|
const registerAuthUser = functions__namespace
|
|
523
561
|
.region("europe-west1")
|
|
524
562
|
.runWith({
|
|
525
|
-
memory: "
|
|
563
|
+
memory: "1GB"
|
|
526
564
|
})
|
|
527
565
|
.auth.user()
|
|
528
566
|
.onCreate(async (user) => {
|
|
@@ -554,11 +592,11 @@ const registerAuthUser = functions__namespace
|
|
|
554
592
|
email === process.env.CUSTOM_CLAIMS_COORDINATOR_EMAIL_ADDRESS_OR_DOMAIN)) {
|
|
555
593
|
const auth = admin.auth();
|
|
556
594
|
// if provider == github.com let's use our functions to check the user's reputation
|
|
557
|
-
if (user.providerData[0].providerId === "github.com") {
|
|
595
|
+
if (user.providerData.length > 0 && user.providerData[0].providerId === "github.com") {
|
|
558
596
|
const vars = getGitHubVariables();
|
|
559
597
|
// this return true or false
|
|
560
598
|
try {
|
|
561
|
-
const { reputable, avatarUrl: avatarURL } = await actions.githubReputation(user.providerData[0].uid, vars.minimumFollowing, vars.minimumFollowers, vars.minimumPublicRepos);
|
|
599
|
+
const { reputable, avatarUrl: avatarURL } = await actions.githubReputation(user.providerData[0].uid, vars.minimumFollowing, vars.minimumFollowers, vars.minimumPublicRepos, vars.minimumAge);
|
|
562
600
|
if (!reputable) {
|
|
563
601
|
// Delete user
|
|
564
602
|
await auth.deleteUser(user.uid);
|
|
@@ -586,7 +624,7 @@ const registerAuthUser = functions__namespace
|
|
|
586
624
|
encodedDisplayName,
|
|
587
625
|
// Metadata.
|
|
588
626
|
creationTime,
|
|
589
|
-
lastSignInTime,
|
|
627
|
+
lastSignInTime: lastSignInTime || creationTime,
|
|
590
628
|
// Optional.
|
|
591
629
|
email: email || "",
|
|
592
630
|
emailVerified: emailVerified || false,
|
|
@@ -609,7 +647,7 @@ const registerAuthUser = functions__namespace
|
|
|
609
647
|
const processSignUpWithCustomClaims = functions__namespace
|
|
610
648
|
.region("europe-west1")
|
|
611
649
|
.runWith({
|
|
612
|
-
memory: "
|
|
650
|
+
memory: "1GB"
|
|
613
651
|
})
|
|
614
652
|
.auth.user()
|
|
615
653
|
.onCreate(async (user) => {
|
|
@@ -650,7 +688,7 @@ dotenv.config();
|
|
|
650
688
|
const startCeremony = functions__namespace
|
|
651
689
|
.region("europe-west1")
|
|
652
690
|
.runWith({
|
|
653
|
-
memory: "
|
|
691
|
+
memory: "1GB"
|
|
654
692
|
})
|
|
655
693
|
.pubsub.schedule(`every 30 minutes`)
|
|
656
694
|
.onRun(async () => {
|
|
@@ -672,7 +710,7 @@ const startCeremony = functions__namespace
|
|
|
672
710
|
const stopCeremony = functions__namespace
|
|
673
711
|
.region("europe-west1")
|
|
674
712
|
.runWith({
|
|
675
|
-
memory: "
|
|
713
|
+
memory: "1GB"
|
|
676
714
|
})
|
|
677
715
|
.pubsub.schedule(`every 30 minutes`)
|
|
678
716
|
.onRun(async () => {
|
|
@@ -694,7 +732,7 @@ const stopCeremony = functions__namespace
|
|
|
694
732
|
const setupCeremony = functions__namespace
|
|
695
733
|
.region("europe-west1")
|
|
696
734
|
.runWith({
|
|
697
|
-
memory: "
|
|
735
|
+
memory: "1GB"
|
|
698
736
|
})
|
|
699
737
|
.https.onCall(async (data, context) => {
|
|
700
738
|
// Check if the user has the coordinator claim.
|
|
@@ -732,7 +770,9 @@ const setupCeremony = functions__namespace
|
|
|
732
770
|
// The VM unique identifier (if any).
|
|
733
771
|
let vmInstanceId = "";
|
|
734
772
|
// Get a new circuit document.
|
|
735
|
-
const
|
|
773
|
+
const ccp = actions.getCircuitsCollectionPath(ceremonyDoc.ref.id);
|
|
774
|
+
printLog(`CircuitsCollectionPath = ${ccp}`, LogLevel.DEBUG);
|
|
775
|
+
const circuitDoc = await firestore.collection(ccp).doc().get();
|
|
736
776
|
// Check if using the VM approach for contribution verification.
|
|
737
777
|
if (circuit.verification.cfOrVm === "VM" /* CircuitContributionVerificationMechanism.VM */) {
|
|
738
778
|
// VM command to be run at the startup.
|
|
@@ -769,12 +809,14 @@ const setupCeremony = functions__namespace
|
|
|
769
809
|
}
|
|
770
810
|
// Encode circuit data.
|
|
771
811
|
const encodedCircuit = htmlEncodeCircuitData(circuit);
|
|
812
|
+
printLog(`writing circuit data...`, LogLevel.DEBUG);
|
|
772
813
|
// Prepare tx to write circuit data.
|
|
773
814
|
batch.create(circuitDoc.ref, {
|
|
774
815
|
...encodedCircuit,
|
|
775
816
|
lastUpdated: getCurrentServerTimestampInMillis()
|
|
776
817
|
});
|
|
777
818
|
}
|
|
819
|
+
printLog(`Done handling circuits...`, LogLevel.DEBUG);
|
|
778
820
|
// Send txs in a batch (to avoid race conditions).
|
|
779
821
|
await batch.commit();
|
|
780
822
|
printLog(`Setup completed for ceremony ${ceremonyDoc.id}`, LogLevel.DEBUG);
|
|
@@ -787,7 +829,7 @@ const setupCeremony = functions__namespace
|
|
|
787
829
|
const initEmptyWaitingQueueForCircuit = functions__namespace
|
|
788
830
|
.region("europe-west1")
|
|
789
831
|
.runWith({
|
|
790
|
-
memory: "
|
|
832
|
+
memory: "1GB"
|
|
791
833
|
})
|
|
792
834
|
.firestore.document(`/${actions.commonTerms.collections.ceremonies.name}/{ceremony}/${actions.commonTerms.collections.circuits.name}/{circuit}`)
|
|
793
835
|
.onCreate(async (doc) => {
|
|
@@ -819,7 +861,7 @@ const initEmptyWaitingQueueForCircuit = functions__namespace
|
|
|
819
861
|
const finalizeCeremony = functions__namespace
|
|
820
862
|
.region("europe-west1")
|
|
821
863
|
.runWith({
|
|
822
|
-
memory: "
|
|
864
|
+
memory: "1GB"
|
|
823
865
|
})
|
|
824
866
|
.https.onCall(async (data, context) => {
|
|
825
867
|
if (!context.auth || !context.auth.token.coordinator)
|
|
@@ -840,7 +882,7 @@ const finalizeCeremony = functions__namespace
|
|
|
840
882
|
// Get ceremony circuits.
|
|
841
883
|
const circuits = await getCeremonyCircuits(ceremonyId);
|
|
842
884
|
// Get final contribution for each circuit.
|
|
843
|
-
// nb. the `getFinalContributionDocument` checks the
|
|
885
|
+
// nb. the `getFinalContributionDocument` checks the existence of the final contribution document (if not present, throws).
|
|
844
886
|
// Therefore, we just need to call the method without taking any data to verify the pre-condition of having already computed
|
|
845
887
|
// the final contributions for each ceremony circuit.
|
|
846
888
|
for await (const circuit of circuits)
|
|
@@ -895,7 +937,7 @@ dotenv.config();
|
|
|
895
937
|
const checkParticipantForCeremony = functions__namespace
|
|
896
938
|
.region("europe-west1")
|
|
897
939
|
.runWith({
|
|
898
|
-
memory: "
|
|
940
|
+
memory: "1GB"
|
|
899
941
|
})
|
|
900
942
|
.https.onCall(async (data, context) => {
|
|
901
943
|
if (!context.auth || (!context.auth.token.participant && !context.auth.token.coordinator))
|
|
@@ -964,7 +1006,7 @@ const checkParticipantForCeremony = functions__namespace
|
|
|
964
1006
|
participantDoc.ref.update({
|
|
965
1007
|
status: "EXHUMED" /* ParticipantStatus.EXHUMED */,
|
|
966
1008
|
contributions,
|
|
967
|
-
tempContributionData: tempContributionData
|
|
1009
|
+
tempContributionData: tempContributionData || firestore.FieldValue.delete(),
|
|
968
1010
|
contributionStep: "DOWNLOADING" /* ParticipantContributionStep.DOWNLOADING */,
|
|
969
1011
|
contributionStartedAt: 0,
|
|
970
1012
|
verificationStartedAt: firestore.FieldValue.delete(),
|
|
@@ -999,7 +1041,7 @@ const checkParticipantForCeremony = functions__namespace
|
|
|
999
1041
|
const progressToNextCircuitForContribution = functions__namespace
|
|
1000
1042
|
.region("europe-west1")
|
|
1001
1043
|
.runWith({
|
|
1002
|
-
memory: "
|
|
1044
|
+
memory: "1GB"
|
|
1003
1045
|
})
|
|
1004
1046
|
.https.onCall(async (data, context) => {
|
|
1005
1047
|
if (!context.auth || (!context.auth.token.participant && !context.auth.token.coordinator))
|
|
@@ -1046,7 +1088,7 @@ const progressToNextCircuitForContribution = functions__namespace
|
|
|
1046
1088
|
const progressToNextContributionStep = functions__namespace
|
|
1047
1089
|
.region("europe-west1")
|
|
1048
1090
|
.runWith({
|
|
1049
|
-
memory: "
|
|
1091
|
+
memory: "1GB"
|
|
1050
1092
|
})
|
|
1051
1093
|
.https.onCall(async (data, context) => {
|
|
1052
1094
|
if (!context.auth || (!context.auth.token.participant && !context.auth.token.coordinator))
|
|
@@ -1097,7 +1139,7 @@ const progressToNextContributionStep = functions__namespace
|
|
|
1097
1139
|
const permanentlyStoreCurrentContributionTimeAndHash = functions__namespace
|
|
1098
1140
|
.region("europe-west1")
|
|
1099
1141
|
.runWith({
|
|
1100
|
-
memory: "
|
|
1142
|
+
memory: "1GB"
|
|
1101
1143
|
})
|
|
1102
1144
|
.https.onCall(async (data, context) => {
|
|
1103
1145
|
if (!context.auth || (!context.auth.token.participant && !context.auth.token.coordinator))
|
|
@@ -1139,7 +1181,7 @@ const permanentlyStoreCurrentContributionTimeAndHash = functions__namespace
|
|
|
1139
1181
|
const temporaryStoreCurrentContributionMultiPartUploadId = functions__namespace
|
|
1140
1182
|
.region("europe-west1")
|
|
1141
1183
|
.runWith({
|
|
1142
|
-
memory: "
|
|
1184
|
+
memory: "1GB"
|
|
1143
1185
|
})
|
|
1144
1186
|
.https.onCall(async (data, context) => {
|
|
1145
1187
|
if (!context.auth || (!context.auth.token.participant && !context.auth.token.coordinator))
|
|
@@ -1177,7 +1219,7 @@ const temporaryStoreCurrentContributionMultiPartUploadId = functions__namespace
|
|
|
1177
1219
|
const temporaryStoreCurrentContributionUploadedChunkData = functions__namespace
|
|
1178
1220
|
.region("europe-west1")
|
|
1179
1221
|
.runWith({
|
|
1180
|
-
memory: "
|
|
1222
|
+
memory: "1GB"
|
|
1181
1223
|
})
|
|
1182
1224
|
.https.onCall(async (data, context) => {
|
|
1183
1225
|
if (!context.auth || (!context.auth.token.participant && !context.auth.token.coordinator))
|
|
@@ -1219,7 +1261,7 @@ const temporaryStoreCurrentContributionUploadedChunkData = functions__namespace
|
|
|
1219
1261
|
const checkAndPrepareCoordinatorForFinalization = functions__namespace
|
|
1220
1262
|
.region("europe-west1")
|
|
1221
1263
|
.runWith({
|
|
1222
|
-
memory: "
|
|
1264
|
+
memory: "1GB"
|
|
1223
1265
|
})
|
|
1224
1266
|
.https.onCall(async (data, context) => {
|
|
1225
1267
|
if (!context.auth || !context.auth.token.coordinator)
|
|
@@ -1296,7 +1338,7 @@ const coordinate = async (participant, circuit, isSingleParticipantCoordination,
|
|
|
1296
1338
|
if (isSingleParticipantCoordination) {
|
|
1297
1339
|
// Scenario (A).
|
|
1298
1340
|
if (emptyWaitingQueue) {
|
|
1299
|
-
printLog(`Coordinate - executing scenario A - emptyWaitingQueue`, LogLevel.
|
|
1341
|
+
printLog(`Coordinate - executing scenario A - emptyWaitingQueue`, LogLevel.INFO);
|
|
1300
1342
|
// Update.
|
|
1301
1343
|
newCurrentContributorId = participant.id;
|
|
1302
1344
|
newParticipantStatus = "CONTRIBUTING" /* ParticipantStatus.CONTRIBUTING */;
|
|
@@ -1305,14 +1347,14 @@ const coordinate = async (participant, circuit, isSingleParticipantCoordination,
|
|
|
1305
1347
|
}
|
|
1306
1348
|
// Scenario (A).
|
|
1307
1349
|
else if (participantResumingAfterTimeoutExpiration) {
|
|
1308
|
-
printLog(`Coordinate - executing scenario A - single - participantResumingAfterTimeoutExpiration`, LogLevel.
|
|
1350
|
+
printLog(`Coordinate - executing scenario A - single - participantResumingAfterTimeoutExpiration`, LogLevel.INFO);
|
|
1309
1351
|
newParticipantStatus = "CONTRIBUTING" /* ParticipantStatus.CONTRIBUTING */;
|
|
1310
1352
|
newContributionStep = "DOWNLOADING" /* ParticipantContributionStep.DOWNLOADING */;
|
|
1311
1353
|
newCurrentContributorId = participant.id;
|
|
1312
1354
|
}
|
|
1313
1355
|
// Scenario (B).
|
|
1314
1356
|
else if (participantIsNotCurrentContributor) {
|
|
1315
|
-
printLog(`Coordinate - executing scenario B - single - participantIsNotCurrentContributor`, LogLevel.
|
|
1357
|
+
printLog(`Coordinate - executing scenario B - single - participantIsNotCurrentContributor`, LogLevel.INFO);
|
|
1316
1358
|
newCurrentContributorId = currentContributor;
|
|
1317
1359
|
newParticipantStatus = "WAITING" /* ParticipantStatus.WAITING */;
|
|
1318
1360
|
newContributors.push(participant.id);
|
|
@@ -1331,7 +1373,7 @@ const coordinate = async (participant, circuit, isSingleParticipantCoordination,
|
|
|
1331
1373
|
});
|
|
1332
1374
|
}
|
|
1333
1375
|
else if (participantIsCurrentContributor && participantCompletedOneOrAllContributions && !!ceremonyId) {
|
|
1334
|
-
printLog(`Coordinate - executing scenario C - multi - participantIsCurrentContributor && participantCompletedOneOrAllContributions`, LogLevel.
|
|
1376
|
+
printLog(`Coordinate - executing scenario C - multi - participantIsCurrentContributor && participantCompletedOneOrAllContributions`, LogLevel.INFO);
|
|
1335
1377
|
newParticipantStatus = "CONTRIBUTING" /* ParticipantStatus.CONTRIBUTING */;
|
|
1336
1378
|
newContributionStep = "DOWNLOADING" /* ParticipantContributionStep.DOWNLOADING */;
|
|
1337
1379
|
// Remove from waiting queue of circuit X.
|
|
@@ -1349,7 +1391,7 @@ const coordinate = async (participant, circuit, isSingleParticipantCoordination,
|
|
|
1349
1391
|
contributionStartedAt: getCurrentServerTimestampInMillis(),
|
|
1350
1392
|
lastUpdated: getCurrentServerTimestampInMillis()
|
|
1351
1393
|
});
|
|
1352
|
-
printLog(`Participant ${newCurrentContributorId} is the new current contributor for circuit ${circuit.id}`, LogLevel.
|
|
1394
|
+
printLog(`Participant ${newCurrentContributorId} is the new current contributor for circuit ${circuit.id}`, LogLevel.INFO);
|
|
1353
1395
|
}
|
|
1354
1396
|
}
|
|
1355
1397
|
// Prepare tx - must be done for all Scenarios.
|
|
@@ -1426,8 +1468,8 @@ const waitForVMCommandExecution = (ssm, vmInstanceId, commandId) => new Promise(
|
|
|
1426
1468
|
try {
|
|
1427
1469
|
await actions.stopEC2Instance(ec2, vmInstanceId);
|
|
1428
1470
|
}
|
|
1429
|
-
catch (
|
|
1430
|
-
printLog(`Error while stopping VM instance ${vmInstanceId} - Error ${
|
|
1471
|
+
catch (stopError) {
|
|
1472
|
+
printLog(`Error while stopping VM instance ${vmInstanceId} - Error ${stopError}`, LogLevel.WARN);
|
|
1431
1473
|
}
|
|
1432
1474
|
if (!error.toString().includes(commandId))
|
|
1433
1475
|
logAndThrowError(COMMON_ERRORS.CM_INVALID_COMMAND_EXECUTION);
|
|
@@ -1459,7 +1501,7 @@ const waitForVMCommandExecution = (ssm, vmInstanceId, commandId) => new Promise(
|
|
|
1459
1501
|
const coordinateCeremonyParticipant = functionsV1__namespace
|
|
1460
1502
|
.region("europe-west1")
|
|
1461
1503
|
.runWith({
|
|
1462
|
-
memory: "
|
|
1504
|
+
memory: "1GB"
|
|
1463
1505
|
})
|
|
1464
1506
|
.firestore.document(`${actions.commonTerms.collections.ceremonies.name}/{ceremonyId}/${actions.commonTerms.collections.participants.name}/{participantId}`)
|
|
1465
1507
|
.onUpdate(async (participantChanges) => {
|
|
@@ -1475,8 +1517,8 @@ const coordinateCeremonyParticipant = functionsV1__namespace
|
|
|
1475
1517
|
// Extract data.
|
|
1476
1518
|
const { contributionProgress: prevContributionProgress, status: prevStatus, contributionStep: prevContributionStep } = exParticipant.data();
|
|
1477
1519
|
const { contributionProgress: changedContributionProgress, status: changedStatus, contributionStep: changedContributionStep } = changedParticipant.data();
|
|
1478
|
-
printLog(`Coordinate participant ${exParticipant.id} for ceremony ${ceremonyId}`, LogLevel.
|
|
1479
|
-
printLog(`Participant status: ${prevStatus} => ${changedStatus} - Participant contribution step: ${prevContributionStep} => ${changedContributionStep}`, LogLevel.
|
|
1520
|
+
printLog(`Coordinate participant ${exParticipant.id} for ceremony ${ceremonyId}`, LogLevel.INFO);
|
|
1521
|
+
printLog(`Participant status: ${prevStatus} => ${changedStatus} - Participant contribution step: ${prevContributionStep} => ${changedContributionStep}`, LogLevel.INFO);
|
|
1480
1522
|
// Define pre-conditions.
|
|
1481
1523
|
const participantReadyToContribute = changedStatus === "READY" /* ParticipantStatus.READY */;
|
|
1482
1524
|
const participantReadyForFirstContribution = participantReadyToContribute && prevContributionProgress === 0;
|
|
@@ -1486,8 +1528,8 @@ const coordinateCeremonyParticipant = functionsV1__namespace
|
|
|
1486
1528
|
prevContributionProgress !== 0;
|
|
1487
1529
|
const participantCompletedEveryCircuitContribution = changedStatus === "DONE" /* ParticipantStatus.DONE */ && prevStatus !== "DONE" /* ParticipantStatus.DONE */;
|
|
1488
1530
|
const participantCompletedContribution = prevContributionProgress === changedContributionProgress &&
|
|
1489
|
-
prevStatus === "CONTRIBUTING" /* ParticipantStatus.CONTRIBUTING */
|
|
1490
|
-
|
|
1531
|
+
(prevStatus === "CONTRIBUTING" /* ParticipantStatus.CONTRIBUTING */ ||
|
|
1532
|
+
prevContributionStep === "VERIFYING" /* ParticipantContributionStep.VERIFYING */) &&
|
|
1491
1533
|
changedStatus === "CONTRIBUTED" /* ParticipantStatus.CONTRIBUTED */ &&
|
|
1492
1534
|
changedContributionStep === "COMPLETED" /* ParticipantContributionStep.COMPLETED */;
|
|
1493
1535
|
// Step (2).
|
|
@@ -1495,7 +1537,7 @@ const coordinateCeremonyParticipant = functionsV1__namespace
|
|
|
1495
1537
|
participantResumingContributionAfterTimeout ||
|
|
1496
1538
|
participantReadyForNextContribution) {
|
|
1497
1539
|
// Step (2.A).
|
|
1498
|
-
printLog(`Participant is ready for first contribution (${participantReadyForFirstContribution}) or for the next contribution (${participantReadyForNextContribution}) or is resuming after a timeout expiration (${participantResumingContributionAfterTimeout})`, LogLevel.
|
|
1540
|
+
printLog(`Participant is ready for first contribution (${participantReadyForFirstContribution}) or for the next contribution (${participantReadyForNextContribution}) or is resuming after a timeout expiration (${participantResumingContributionAfterTimeout})`, LogLevel.INFO);
|
|
1499
1541
|
// Get the circuit.
|
|
1500
1542
|
const circuit = await getCircuitDocumentByPosition(ceremonyId, changedContributionProgress);
|
|
1501
1543
|
// Coordinate.
|
|
@@ -1504,7 +1546,7 @@ const coordinateCeremonyParticipant = functionsV1__namespace
|
|
|
1504
1546
|
}
|
|
1505
1547
|
else if (participantCompletedContribution || participantCompletedEveryCircuitContribution) {
|
|
1506
1548
|
// Step (2.B).
|
|
1507
|
-
printLog(`Participant completed a contribution (${participantCompletedContribution}) or every contribution for each circuit (${participantCompletedEveryCircuitContribution})`, LogLevel.
|
|
1549
|
+
printLog(`Participant completed a contribution (${participantCompletedContribution}) or every contribution for each circuit (${participantCompletedEveryCircuitContribution})`, LogLevel.INFO);
|
|
1508
1550
|
// Get the circuit.
|
|
1509
1551
|
const circuit = await getCircuitDocumentByPosition(ceremonyId, prevContributionProgress);
|
|
1510
1552
|
// Coordinate.
|
|
@@ -1528,11 +1570,9 @@ const checkIfVMRunning = async (ec2, vmInstanceId, attempts = 5) => {
|
|
|
1528
1570
|
const isVMRunning = await actions.checkIfRunning(ec2, vmInstanceId);
|
|
1529
1571
|
if (!isVMRunning) {
|
|
1530
1572
|
printLog(`VM not running, ${attempts - 1} attempts remaining. Retrying in 1 minute...`, LogLevel.DEBUG);
|
|
1531
|
-
return
|
|
1532
|
-
}
|
|
1533
|
-
else {
|
|
1534
|
-
return true;
|
|
1573
|
+
return checkIfVMRunning(ec2, vmInstanceId, attempts - 1);
|
|
1535
1574
|
}
|
|
1575
|
+
return true;
|
|
1536
1576
|
};
|
|
1537
1577
|
/**
|
|
1538
1578
|
* Verify the contribution of a participant computed while contributing to a specific circuit of a ceremony.
|
|
@@ -1560,297 +1600,325 @@ const checkIfVMRunning = async (ec2, vmInstanceId, attempts = 5) => {
|
|
|
1560
1600
|
* 1.A.4.C.1) If true, update circuit waiting for queue and average timings accordingly to contribution verification results;
|
|
1561
1601
|
* 2) Send all updates atomically to the Firestore database.
|
|
1562
1602
|
*/
|
|
1563
|
-
const verifycontribution = functionsV2__namespace.https.onCall({ memory: "
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
!request.data.
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
!process.env.
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
//
|
|
1634
|
-
|
|
1635
|
-
verificationTaskTimer.
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
// Download from bucket.
|
|
1642
|
-
// nb. the transcript MUST be uploaded from the VM by verification commands.
|
|
1643
|
-
await downloadArtifactFromS3Bucket(bucketName, verificationTranscriptStoragePathAndFilename, verificationTranscriptTemporaryLocalPath);
|
|
1644
|
-
// Read the verification trascript and validate data by checking for core info ("ZKey Ok!").
|
|
1645
|
-
const content = fs.readFileSync(verificationTranscriptTemporaryLocalPath, "utf-8");
|
|
1646
|
-
if (content.includes("ZKey Ok!"))
|
|
1647
|
-
isContributionValid = true;
|
|
1648
|
-
// If the contribution is valid, then format and store the trascript.
|
|
1649
|
-
if (isContributionValid) {
|
|
1650
|
-
// eslint-disable-next-line no-control-regex
|
|
1651
|
-
const updated = content.replace(/\x1b[[0-9;]*m/g, "");
|
|
1652
|
-
fs.writeFileSync(verificationTranscriptTemporaryLocalPath, updated);
|
|
1603
|
+
const verifycontribution = functionsV2__namespace.https.onCall({ memory: "32GiB", timeoutSeconds: 3600, region: "europe-west1", cpu: 8 }, async (request) => {
|
|
1604
|
+
try {
|
|
1605
|
+
if (!request.auth || (!request.auth.token.participant && !request.auth.token.coordinator))
|
|
1606
|
+
logAndThrowError(SPECIFIC_ERRORS.SE_AUTH_NO_CURRENT_AUTH_USER);
|
|
1607
|
+
if (!request.data.ceremonyId ||
|
|
1608
|
+
!request.data.circuitId ||
|
|
1609
|
+
!request.data.contributorOrCoordinatorIdentifier ||
|
|
1610
|
+
!request.data.bucketName)
|
|
1611
|
+
logAndThrowError(COMMON_ERRORS.CM_MISSING_OR_WRONG_INPUT_DATA);
|
|
1612
|
+
if (!process.env.CUSTOM_CONTRIBUTION_VERIFICATION_SOFTWARE_NAME ||
|
|
1613
|
+
!process.env.CUSTOM_CONTRIBUTION_VERIFICATION_SOFTWARE_VERSION ||
|
|
1614
|
+
!process.env.CUSTOM_CONTRIBUTION_VERIFICATION_SOFTWARE_COMMIT_HASH)
|
|
1615
|
+
logAndThrowError(COMMON_ERRORS.CM_WRONG_CONFIGURATION);
|
|
1616
|
+
const BUCKET_NAME_REGEX = /^[a-z0-9][a-z0-9-]{1,61}[a-z0-9]$/;
|
|
1617
|
+
if (!BUCKET_NAME_REGEX.test(request.data.bucketName))
|
|
1618
|
+
logAndThrowError(SPECIFIC_ERRORS.WRONG_BUCKET_NAME);
|
|
1619
|
+
// Step (0).
|
|
1620
|
+
// Prepare and start timer.
|
|
1621
|
+
const verifyContributionTimer = new timerNode.Timer({ label: actions.commonTerms.cloudFunctionsNames.verifyContribution });
|
|
1622
|
+
verifyContributionTimer.start();
|
|
1623
|
+
// Get DB.
|
|
1624
|
+
const firestore = admin.firestore();
|
|
1625
|
+
// Prepare batch of txs.
|
|
1626
|
+
const batch = firestore.batch();
|
|
1627
|
+
// Extract data.
|
|
1628
|
+
const { ceremonyId, circuitId, contributorOrCoordinatorIdentifier, bucketName } = request.data;
|
|
1629
|
+
const userId = request.auth?.uid;
|
|
1630
|
+
// Look for the ceremony, circuit and participant document.
|
|
1631
|
+
const ceremonyDoc = await getDocumentById(actions.commonTerms.collections.ceremonies.name, ceremonyId);
|
|
1632
|
+
const circuitDoc = await getDocumentById(actions.getCircuitsCollectionPath(ceremonyId), circuitId);
|
|
1633
|
+
const participantDoc = await getDocumentById(actions.getParticipantsCollectionPath(ceremonyId), userId);
|
|
1634
|
+
if (!ceremonyDoc.data() || !circuitDoc.data() || !participantDoc.data())
|
|
1635
|
+
logAndThrowError(COMMON_ERRORS.CM_INEXISTENT_DOCUMENT_DATA);
|
|
1636
|
+
// Extract documents data.
|
|
1637
|
+
const { state } = ceremonyDoc.data();
|
|
1638
|
+
const { status, contributions, verificationStartedAt, contributionStartedAt } = participantDoc.data();
|
|
1639
|
+
const { waitingQueue, prefix, avgTimings, verification, files } = circuitDoc.data();
|
|
1640
|
+
const { completedContributions, failedContributions } = waitingQueue;
|
|
1641
|
+
const { contributionComputation: avgContributionComputationTime, fullContribution: avgFullContributionTime, verifyCloudFunction: avgVerifyCloudFunctionTime } = avgTimings;
|
|
1642
|
+
const { cfOrVm, vm } = verification;
|
|
1643
|
+
// we might not have it if the circuit is not using VM.
|
|
1644
|
+
let vmInstanceId = "";
|
|
1645
|
+
if (vm)
|
|
1646
|
+
vmInstanceId = vm.vmInstanceId;
|
|
1647
|
+
// Define pre-conditions.
|
|
1648
|
+
const isFinalizing = state === "CLOSED" /* CeremonyState.CLOSED */ && request.auth && request.auth.token.coordinator; // true only when the coordinator verifies the final contributions.
|
|
1649
|
+
const isContributing = status === "CONTRIBUTING" /* ParticipantStatus.CONTRIBUTING */;
|
|
1650
|
+
const isUsingVM = cfOrVm === "VM" /* CircuitContributionVerificationMechanism.VM */ && !!vmInstanceId;
|
|
1651
|
+
// Prepare state.
|
|
1652
|
+
let isContributionValid = false;
|
|
1653
|
+
let verifyCloudFunctionExecutionTime = 0; // time spent while executing the verify contribution cloud function.
|
|
1654
|
+
let verifyCloudFunctionTime = 0; // time spent while executing the core business logic of this cloud function.
|
|
1655
|
+
let fullContributionTime = 0; // time spent while doing non-verification contributions tasks (download, compute, upload).
|
|
1656
|
+
let contributionComputationTime = 0; // time spent while computing the contribution.
|
|
1657
|
+
let lastZkeyBlake2bHash = ""; // the Blake2B hash of the last zKey.
|
|
1658
|
+
let verificationTranscriptTemporaryLocalPath = ""; // the local temporary path for the verification transcript.
|
|
1659
|
+
let transcriptBlake2bHash = ""; // the Blake2B hash of the verification transcript.
|
|
1660
|
+
let commandId = ""; // the unique identifier of the VM command.
|
|
1661
|
+
// Derive necessary data.
|
|
1662
|
+
const lastZkeyIndex = actions.formatZkeyIndex(completedContributions + 1);
|
|
1663
|
+
const verificationTranscriptCompleteFilename = `${prefix}_${isFinalizing
|
|
1664
|
+
? `${contributorOrCoordinatorIdentifier}_${actions.finalContributionIndex}_verification_transcript.log`
|
|
1665
|
+
: `${lastZkeyIndex}_${contributorOrCoordinatorIdentifier}_verification_transcript.log`}`;
|
|
1666
|
+
const lastZkeyFilename = `${prefix}_${isFinalizing ? actions.finalContributionIndex : lastZkeyIndex}.zkey`;
|
|
1667
|
+
// Prepare state for VM verification (if needed).
|
|
1668
|
+
const ec2 = await createEC2Client();
|
|
1669
|
+
const ssm = await createSSMClient();
|
|
1670
|
+
// Step (1.A.1).
|
|
1671
|
+
// Get storage paths.
|
|
1672
|
+
const verificationTranscriptStoragePathAndFilename = actions.getTranscriptStorageFilePath(prefix, verificationTranscriptCompleteFilename);
|
|
1673
|
+
// the zKey storage path is required to be sent to the VM api
|
|
1674
|
+
const lastZkeyStoragePath = actions.getZkeyStorageFilePath(prefix, `${prefix}_${isFinalizing ? actions.finalContributionIndex : lastZkeyIndex}.zkey`);
|
|
1675
|
+
const verificationTaskTimer = new timerNode.Timer({ label: `${ceremonyId}-${circuitId}-${participantDoc.id}` });
|
|
1676
|
+
const dumpLog = async (path) => {
|
|
1677
|
+
printLog(`transcript >>>>>>`, LogLevel.DEBUG);
|
|
1678
|
+
try {
|
|
1679
|
+
const data = await fs.promises.readFile(path, "utf8");
|
|
1680
|
+
printLog(data, LogLevel.DEBUG);
|
|
1653
1681
|
}
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
.
|
|
1660
|
-
.
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
// Sleep ~3 seconds to wait for verification transcription.
|
|
1664
|
-
await sleep(3000);
|
|
1665
|
-
// Step (1.A.4.A.1).
|
|
1682
|
+
catch (readError) {
|
|
1683
|
+
printLog(readError, LogLevel.ERROR);
|
|
1684
|
+
}
|
|
1685
|
+
};
|
|
1686
|
+
const completeVerification = async () => {
|
|
1687
|
+
// Stop verification task timer.
|
|
1688
|
+
printLog("Completing verification", LogLevel.DEBUG);
|
|
1689
|
+
verificationTaskTimer.stop();
|
|
1690
|
+
verifyCloudFunctionExecutionTime = verificationTaskTimer.ms();
|
|
1666
1691
|
if (isUsingVM) {
|
|
1667
|
-
//
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1692
|
+
// Create temporary path.
|
|
1693
|
+
verificationTranscriptTemporaryLocalPath = createTemporaryLocalPath(`${circuitId}_${participantDoc.id}.log`);
|
|
1694
|
+
await sleep(1000); // wait 1s for file creation.
|
|
1695
|
+
// Download from bucket.
|
|
1696
|
+
// nb. the transcript MUST be uploaded from the VM by verification commands.
|
|
1697
|
+
await downloadArtifactFromS3Bucket(bucketName, verificationTranscriptStoragePathAndFilename, verificationTranscriptTemporaryLocalPath);
|
|
1698
|
+
// Read the verification trascript and validate data by checking for core info ("ZKey Ok!").
|
|
1699
|
+
const content = fs.readFileSync(verificationTranscriptTemporaryLocalPath, "utf-8");
|
|
1700
|
+
if (content.includes("ZKey Ok!"))
|
|
1701
|
+
isContributionValid = true;
|
|
1702
|
+
// If the contribution is valid, then format and store the trascript.
|
|
1703
|
+
if (isContributionValid) {
|
|
1704
|
+
// eslint-disable-next-line no-control-regex
|
|
1705
|
+
const updated = content.replace(/\x1b[[0-9;]*m/g, "");
|
|
1706
|
+
fs.writeFileSync(verificationTranscriptTemporaryLocalPath, updated);
|
|
1707
|
+
}
|
|
1708
|
+
}
|
|
1709
|
+
printLog(`The contribution has been verified - Result ${isContributionValid}`, LogLevel.DEBUG);
|
|
1710
|
+
// Create a new contribution document.
|
|
1711
|
+
const contributionDoc = await firestore
|
|
1712
|
+
.collection(actions.getContributionsCollectionPath(ceremonyId, circuitId))
|
|
1713
|
+
.doc()
|
|
1714
|
+
.get();
|
|
1715
|
+
// Step (1.A.4).
|
|
1716
|
+
if (isContributionValid) {
|
|
1717
|
+
// Sleep ~3 seconds to wait for verification transcription.
|
|
1718
|
+
await sleep(3000);
|
|
1719
|
+
// Step (1.A.4.A.1).
|
|
1720
|
+
if (isUsingVM) {
|
|
1721
|
+
// Retrieve the contribution hash from the command output.
|
|
1722
|
+
lastZkeyBlake2bHash = await actions.retrieveCommandOutput(ssm, vmInstanceId, commandId);
|
|
1723
|
+
const hashRegex = /[a-fA-F0-9]{64}/;
|
|
1724
|
+
const match = lastZkeyBlake2bHash.match(hashRegex);
|
|
1725
|
+
lastZkeyBlake2bHash = match.at(0);
|
|
1726
|
+
// re upload the formatted verification transcript
|
|
1727
|
+
await uploadFileToBucket(bucketName, verificationTranscriptStoragePathAndFilename, verificationTranscriptTemporaryLocalPath, true);
|
|
1728
|
+
}
|
|
1729
|
+
else {
|
|
1730
|
+
// Upload verification transcript.
|
|
1731
|
+
/// nb. do not use multi-part upload here due to small file size.
|
|
1732
|
+
await uploadFileToBucket(bucketName, verificationTranscriptStoragePathAndFilename, verificationTranscriptTemporaryLocalPath, true);
|
|
1733
|
+
}
|
|
1734
|
+
// Compute verification transcript hash.
|
|
1735
|
+
transcriptBlake2bHash = await actions.blake512FromPath(verificationTranscriptTemporaryLocalPath);
|
|
1736
|
+
// Free resources by unlinking transcript temporary file.
|
|
1737
|
+
fs.unlinkSync(verificationTranscriptTemporaryLocalPath);
|
|
1738
|
+
// Filter participant contributions to find the data related to the one verified.
|
|
1739
|
+
const participantContributions = contributions.filter((contribution) => !!contribution.hash && !!contribution.computationTime && !contribution.doc);
|
|
1740
|
+
/// @dev (there must be only one contribution with an empty 'doc' field).
|
|
1741
|
+
if (participantContributions.length !== 1)
|
|
1742
|
+
logAndThrowError(SPECIFIC_ERRORS.SE_VERIFICATION_NO_PARTICIPANT_CONTRIBUTION_DATA);
|
|
1743
|
+
// Get contribution computation time.
|
|
1744
|
+
contributionComputationTime = contributions.at(0).computationTime;
|
|
1745
|
+
// Step (1.A.4.A.2).
|
|
1746
|
+
batch.create(contributionDoc.ref, {
|
|
1747
|
+
participantId: participantDoc.id,
|
|
1748
|
+
contributionComputationTime,
|
|
1749
|
+
verificationComputationTime: verifyCloudFunctionExecutionTime,
|
|
1750
|
+
zkeyIndex: isFinalizing ? actions.finalContributionIndex : lastZkeyIndex,
|
|
1751
|
+
files: {
|
|
1752
|
+
transcriptFilename: verificationTranscriptCompleteFilename,
|
|
1753
|
+
lastZkeyFilename,
|
|
1754
|
+
transcriptStoragePath: verificationTranscriptStoragePathAndFilename,
|
|
1755
|
+
lastZkeyStoragePath,
|
|
1756
|
+
transcriptBlake2bHash,
|
|
1757
|
+
lastZkeyBlake2bHash
|
|
1758
|
+
},
|
|
1759
|
+
verificationSoftware: {
|
|
1760
|
+
name: String(process.env.CUSTOM_CONTRIBUTION_VERIFICATION_SOFTWARE_NAME),
|
|
1761
|
+
version: String(process.env.CUSTOM_CONTRIBUTION_VERIFICATION_SOFTWARE_VERSION),
|
|
1762
|
+
commitHash: String(process.env.CUSTOM_CONTRIBUTION_VERIFICATION_SOFTWARE_COMMIT_HASH)
|
|
1763
|
+
},
|
|
1764
|
+
valid: isContributionValid,
|
|
1765
|
+
lastUpdated: getCurrentServerTimestampInMillis()
|
|
1766
|
+
});
|
|
1767
|
+
verifyContributionTimer.stop();
|
|
1768
|
+
verifyCloudFunctionTime = verifyContributionTimer.ms();
|
|
1674
1769
|
}
|
|
1675
1770
|
else {
|
|
1676
|
-
//
|
|
1677
|
-
|
|
1678
|
-
await
|
|
1771
|
+
// Step (1.A.4.B).
|
|
1772
|
+
// Free-up storage by deleting invalid contribution.
|
|
1773
|
+
await deleteObject(bucketName, lastZkeyStoragePath);
|
|
1774
|
+
// Step (1.A.4.B.1).
|
|
1775
|
+
batch.create(contributionDoc.ref, {
|
|
1776
|
+
participantId: participantDoc.id,
|
|
1777
|
+
verificationComputationTime: verifyCloudFunctionExecutionTime,
|
|
1778
|
+
zkeyIndex: isFinalizing ? actions.finalContributionIndex : lastZkeyIndex,
|
|
1779
|
+
verificationSoftware: {
|
|
1780
|
+
name: String(process.env.CUSTOM_CONTRIBUTION_VERIFICATION_SOFTWARE_NAME),
|
|
1781
|
+
version: String(process.env.CUSTOM_CONTRIBUTION_VERIFICATION_SOFTWARE_VERSION),
|
|
1782
|
+
commitHash: String(process.env.CUSTOM_CONTRIBUTION_VERIFICATION_SOFTWARE_COMMIT_HASH)
|
|
1783
|
+
},
|
|
1784
|
+
valid: isContributionValid,
|
|
1785
|
+
lastUpdated: getCurrentServerTimestampInMillis()
|
|
1786
|
+
});
|
|
1679
1787
|
}
|
|
1680
|
-
//
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
//
|
|
1788
|
+
// Stop VM instance
|
|
1789
|
+
if (isUsingVM) {
|
|
1790
|
+
// using try and catch as the VM stopping function can throw
|
|
1791
|
+
// however we want to continue without stopping as the
|
|
1792
|
+
// verification was valid, and inform the coordinator
|
|
1793
|
+
try {
|
|
1794
|
+
await actions.stopEC2Instance(ec2, vmInstanceId);
|
|
1795
|
+
}
|
|
1796
|
+
catch (error) {
|
|
1797
|
+
printLog(`Error while stopping VM instance ${vmInstanceId} - Error ${error}`, LogLevel.WARN);
|
|
1798
|
+
}
|
|
1799
|
+
}
|
|
1800
|
+
// Step (1.A.4.C)
|
|
1801
|
+
if (!isFinalizing) {
|
|
1802
|
+
// Step (1.A.4.C.1)
|
|
1803
|
+
// Compute new average contribution/verification time.
|
|
1804
|
+
fullContributionTime = Number(verificationStartedAt) - Number(contributionStartedAt);
|
|
1805
|
+
const newAvgContributionComputationTime = avgContributionComputationTime > 0
|
|
1806
|
+
? (avgContributionComputationTime + contributionComputationTime) / 2
|
|
1807
|
+
: contributionComputationTime;
|
|
1808
|
+
const newAvgFullContributionTime = avgFullContributionTime > 0
|
|
1809
|
+
? (avgFullContributionTime + fullContributionTime) / 2
|
|
1810
|
+
: fullContributionTime;
|
|
1811
|
+
const newAvgVerifyCloudFunctionTime = avgVerifyCloudFunctionTime > 0
|
|
1812
|
+
? (avgVerifyCloudFunctionTime + verifyCloudFunctionTime) / 2
|
|
1813
|
+
: verifyCloudFunctionTime;
|
|
1814
|
+
// Prepare tx to update circuit average contribution/verification time.
|
|
1815
|
+
const updatedCircuitDoc = await getDocumentById(actions.getCircuitsCollectionPath(ceremonyId), circuitId);
|
|
1816
|
+
const { waitingQueue: updatedWaitingQueue } = updatedCircuitDoc.data();
|
|
1817
|
+
/// @dev this must happen only for valid contributions.
|
|
1818
|
+
batch.update(circuitDoc.ref, {
|
|
1819
|
+
avgTimings: {
|
|
1820
|
+
contributionComputation: isContributionValid
|
|
1821
|
+
? newAvgContributionComputationTime
|
|
1822
|
+
: avgContributionComputationTime,
|
|
1823
|
+
fullContribution: isContributionValid
|
|
1824
|
+
? newAvgFullContributionTime
|
|
1825
|
+
: avgFullContributionTime,
|
|
1826
|
+
verifyCloudFunction: isContributionValid
|
|
1827
|
+
? newAvgVerifyCloudFunctionTime
|
|
1828
|
+
: avgVerifyCloudFunctionTime
|
|
1829
|
+
},
|
|
1830
|
+
waitingQueue: {
|
|
1831
|
+
...updatedWaitingQueue,
|
|
1832
|
+
completedContributions: isContributionValid
|
|
1833
|
+
? completedContributions + 1
|
|
1834
|
+
: completedContributions,
|
|
1835
|
+
failedContributions: isContributionValid ? failedContributions : failedContributions + 1
|
|
1836
|
+
},
|
|
1837
|
+
lastUpdated: getCurrentServerTimestampInMillis()
|
|
1838
|
+
});
|
|
1839
|
+
}
|
|
1840
|
+
// Step (2).
|
|
1841
|
+
await batch.commit();
|
|
1842
|
+
printLog(`The contribution #${isFinalizing ? actions.finalContributionIndex : lastZkeyIndex} of circuit ${circuitId} (ceremony ${ceremonyId}) has been verified as ${isContributionValid ? "valid" : "invalid"} for the participant ${participantDoc.id}`, LogLevel.INFO);
|
|
1843
|
+
};
|
|
1844
|
+
// Step (1).
|
|
1845
|
+
if (isContributing || isFinalizing) {
|
|
1846
|
+
// Prepare timer.
|
|
1847
|
+
verificationTaskTimer.start();
|
|
1848
|
+
// Step (1.A.3.0).
|
|
1849
|
+
if (isUsingVM) {
|
|
1850
|
+
printLog(`Starting the VM mechanism`, LogLevel.DEBUG);
|
|
1851
|
+
// Prepare for VM execution.
|
|
1852
|
+
let isVMRunning = false; // true when the VM is up, otherwise false.
|
|
1853
|
+
// Step (1.A.3.1).
|
|
1854
|
+
await actions.startEC2Instance(ec2, vmInstanceId);
|
|
1855
|
+
await sleep(60000); // nb. wait for VM startup (1 mins + retry).
|
|
1856
|
+
// Check if the startup is running.
|
|
1857
|
+
isVMRunning = await checkIfVMRunning(ec2, vmInstanceId);
|
|
1858
|
+
printLog(`VM running: ${isVMRunning}`, LogLevel.DEBUG);
|
|
1859
|
+
// Step (1.A.3.2).
|
|
1860
|
+
// Prepare.
|
|
1861
|
+
const verificationCommand = actions.vmContributionVerificationCommand(bucketName, lastZkeyStoragePath, verificationTranscriptStoragePathAndFilename);
|
|
1862
|
+
// Run.
|
|
1863
|
+
commandId = await actions.runCommandUsingSSM(ssm, vmInstanceId, verificationCommand);
|
|
1864
|
+
printLog(`Starting the execution of command ${commandId}`, LogLevel.DEBUG);
|
|
1865
|
+
// Step (1.A.3.3).
|
|
1866
|
+
return await waitForVMCommandExecution(ssm, vmInstanceId, commandId)
|
|
1867
|
+
.then(async () => {
|
|
1868
|
+
// Command execution successfully completed.
|
|
1869
|
+
printLog(`Command ${commandId} execution has been successfully completed`, LogLevel.DEBUG);
|
|
1870
|
+
await completeVerification();
|
|
1871
|
+
})
|
|
1872
|
+
.catch((error) => {
|
|
1873
|
+
// Command execution aborted.
|
|
1874
|
+
printLog(`Command ${commandId} execution has been aborted - Error ${error}`, LogLevel.WARN);
|
|
1875
|
+
logAndThrowError(COMMON_ERRORS.CM_INVALID_COMMAND_EXECUTION);
|
|
1876
|
+
});
|
|
1877
|
+
}
|
|
1878
|
+
// CF approach.
|
|
1879
|
+
printLog(`CF mechanism`, LogLevel.DEBUG);
|
|
1880
|
+
const potStoragePath = actions.getPotStorageFilePath(files.potFilename);
|
|
1881
|
+
const firstZkeyStoragePath = actions.getZkeyStorageFilePath(prefix, `${prefix}_${actions.genesisZkeyIndex}.zkey`);
|
|
1882
|
+
printLog(`pot file: ${potStoragePath}`, LogLevel.DEBUG);
|
|
1883
|
+
printLog(`zkey file: ${firstZkeyStoragePath}`, LogLevel.DEBUG);
|
|
1884
|
+
// Prepare temporary file paths.
|
|
1885
|
+
// (nb. these are needed to download the necessary artifacts for verification from AWS S3).
|
|
1886
|
+
verificationTranscriptTemporaryLocalPath = createTemporaryLocalPath(verificationTranscriptCompleteFilename);
|
|
1887
|
+
const potTempFilePath = createTemporaryLocalPath(`${circuitId}_${participantDoc.id}.pot`);
|
|
1888
|
+
const firstZkeyTempFilePath = createTemporaryLocalPath(`${circuitId}_${participantDoc.id}_genesis.zkey`);
|
|
1889
|
+
const lastZkeyTempFilePath = createTemporaryLocalPath(`${circuitId}_${participantDoc.id}_last.zkey`);
|
|
1890
|
+
printLog(`pot file: ${potTempFilePath}`, LogLevel.DEBUG);
|
|
1891
|
+
printLog(`firstZkey file: ${firstZkeyTempFilePath}`, LogLevel.DEBUG);
|
|
1892
|
+
printLog(`last zkey file: ${lastZkeyTempFilePath}`, LogLevel.DEBUG);
|
|
1893
|
+
// Create and populate transcript.
|
|
1894
|
+
const transcriptLogger = actions.createCustomLoggerForFile(verificationTranscriptTemporaryLocalPath);
|
|
1895
|
+
transcriptLogger.info(`${isFinalizing ? `Final verification` : `Verification`} transcript for ${prefix} circuit Phase 2 contribution.\n${isFinalizing ? `Coordinator ` : `Contributor # ${Number(lastZkeyIndex)}`} (${contributorOrCoordinatorIdentifier})\n`);
|
|
1896
|
+
// Step (1.A.2).
|
|
1897
|
+
await downloadArtifactFromS3Bucket(bucketName, potStoragePath, potTempFilePath);
|
|
1898
|
+
await downloadArtifactFromS3Bucket(bucketName, firstZkeyStoragePath, firstZkeyTempFilePath);
|
|
1899
|
+
await downloadArtifactFromS3Bucket(bucketName, lastZkeyStoragePath, lastZkeyTempFilePath);
|
|
1900
|
+
// Step (1.A.4).
|
|
1901
|
+
isContributionValid = await snarkjs.zKey.verifyFromInit(firstZkeyTempFilePath, potTempFilePath, lastZkeyTempFilePath, transcriptLogger);
|
|
1902
|
+
await dumpLog(verificationTranscriptTemporaryLocalPath);
|
|
1903
|
+
// Compute contribution hash.
|
|
1904
|
+
lastZkeyBlake2bHash = await actions.blake512FromPath(lastZkeyTempFilePath);
|
|
1905
|
+
// Free resources by unlinking temporary folders.
|
|
1906
|
+
// Do not free-up verification transcript path here.
|
|
1739
1907
|
try {
|
|
1740
|
-
|
|
1908
|
+
fs.unlinkSync(potTempFilePath);
|
|
1909
|
+
fs.unlinkSync(firstZkeyTempFilePath);
|
|
1910
|
+
fs.unlinkSync(lastZkeyTempFilePath);
|
|
1741
1911
|
}
|
|
1742
1912
|
catch (error) {
|
|
1743
|
-
printLog(`Error while
|
|
1913
|
+
printLog(`Error while unlinking temporary files - Error ${error}`, LogLevel.WARN);
|
|
1744
1914
|
}
|
|
1915
|
+
await completeVerification();
|
|
1745
1916
|
}
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
const newAvgContributionComputationTime = avgContributionComputationTime > 0
|
|
1752
|
-
? (avgContributionComputationTime + contributionComputationTime) / 2
|
|
1753
|
-
: contributionComputationTime;
|
|
1754
|
-
const newAvgFullContributionTime = avgFullContributionTime > 0
|
|
1755
|
-
? (avgFullContributionTime + fullContributionTime) / 2
|
|
1756
|
-
: fullContributionTime;
|
|
1757
|
-
const newAvgVerifyCloudFunctionTime = avgVerifyCloudFunctionTime > 0
|
|
1758
|
-
? (avgVerifyCloudFunctionTime + verifyCloudFunctionTime) / 2
|
|
1759
|
-
: verifyCloudFunctionTime;
|
|
1760
|
-
// Prepare tx to update circuit average contribution/verification time.
|
|
1761
|
-
const updatedCircuitDoc = await getDocumentById(actions.getCircuitsCollectionPath(ceremonyId), circuitId);
|
|
1762
|
-
const { waitingQueue: updatedWaitingQueue } = updatedCircuitDoc.data();
|
|
1763
|
-
/// @dev this must happen only for valid contributions.
|
|
1764
|
-
batch.update(circuitDoc.ref, {
|
|
1765
|
-
avgTimings: {
|
|
1766
|
-
contributionComputation: isContributionValid
|
|
1767
|
-
? newAvgContributionComputationTime
|
|
1768
|
-
: avgContributionComputationTime,
|
|
1769
|
-
fullContribution: isContributionValid ? newAvgFullContributionTime : avgFullContributionTime,
|
|
1770
|
-
verifyCloudFunction: isContributionValid
|
|
1771
|
-
? newAvgVerifyCloudFunctionTime
|
|
1772
|
-
: avgVerifyCloudFunctionTime
|
|
1773
|
-
},
|
|
1774
|
-
waitingQueue: {
|
|
1775
|
-
...updatedWaitingQueue,
|
|
1776
|
-
completedContributions: isContributionValid
|
|
1777
|
-
? completedContributions + 1
|
|
1778
|
-
: completedContributions,
|
|
1779
|
-
failedContributions: isContributionValid ? failedContributions : failedContributions + 1
|
|
1780
|
-
},
|
|
1781
|
-
lastUpdated: getCurrentServerTimestampInMillis()
|
|
1782
|
-
});
|
|
1783
|
-
}
|
|
1784
|
-
// Step (2).
|
|
1785
|
-
await batch.commit();
|
|
1786
|
-
printLog(`The contribution #${isFinalizing ? actions.finalContributionIndex : lastZkeyIndex} of circuit ${circuitId} (ceremony ${ceremonyId}) has been verified as ${isContributionValid ? "valid" : "invalid"} for the participant ${participantDoc.id}`, LogLevel.DEBUG);
|
|
1787
|
-
};
|
|
1788
|
-
// Step (1).
|
|
1789
|
-
if (isContributing || isFinalizing) {
|
|
1790
|
-
// Prepare timer.
|
|
1791
|
-
verificationTaskTimer.start();
|
|
1792
|
-
// Step (1.A.3.0).
|
|
1793
|
-
if (isUsingVM) {
|
|
1794
|
-
printLog(`Starting the VM mechanism`, LogLevel.DEBUG);
|
|
1795
|
-
// Prepare for VM execution.
|
|
1796
|
-
let isVMRunning = false; // true when the VM is up, otherwise false.
|
|
1797
|
-
// Step (1.A.3.1).
|
|
1798
|
-
await actions.startEC2Instance(ec2, vmInstanceId);
|
|
1799
|
-
await sleep(60000); // nb. wait for VM startup (1 mins + retry).
|
|
1800
|
-
// Check if the startup is running.
|
|
1801
|
-
isVMRunning = await checkIfVMRunning(ec2, vmInstanceId);
|
|
1802
|
-
printLog(`VM running: ${isVMRunning}`, LogLevel.DEBUG);
|
|
1803
|
-
// Step (1.A.3.2).
|
|
1804
|
-
// Prepare.
|
|
1805
|
-
const verificationCommand = actions.vmContributionVerificationCommand(bucketName, lastZkeyStoragePath, verificationTranscriptStoragePathAndFilename);
|
|
1806
|
-
// Run.
|
|
1807
|
-
commandId = await actions.runCommandUsingSSM(ssm, vmInstanceId, verificationCommand);
|
|
1808
|
-
printLog(`Starting the execution of command ${commandId}`, LogLevel.DEBUG);
|
|
1809
|
-
// Step (1.A.3.3).
|
|
1810
|
-
return waitForVMCommandExecution(ssm, vmInstanceId, commandId)
|
|
1811
|
-
.then(async () => {
|
|
1812
|
-
// Command execution successfully completed.
|
|
1813
|
-
printLog(`Command ${commandId} execution has been successfully completed`, LogLevel.DEBUG);
|
|
1814
|
-
await completeVerification();
|
|
1815
|
-
})
|
|
1816
|
-
.catch((error) => {
|
|
1817
|
-
// Command execution aborted.
|
|
1818
|
-
printLog(`Command ${commandId} execution has been aborted - Error ${error}`, LogLevel.DEBUG);
|
|
1819
|
-
logAndThrowError(COMMON_ERRORS.CM_INVALID_COMMAND_EXECUTION);
|
|
1820
|
-
});
|
|
1821
|
-
}
|
|
1822
|
-
// CF approach.
|
|
1823
|
-
printLog(`CF mechanism`, LogLevel.DEBUG);
|
|
1824
|
-
const potStoragePath = actions.getPotStorageFilePath(files.potFilename);
|
|
1825
|
-
const firstZkeyStoragePath = actions.getZkeyStorageFilePath(prefix, `${prefix}_${actions.genesisZkeyIndex}.zkey`);
|
|
1826
|
-
// Prepare temporary file paths.
|
|
1827
|
-
// (nb. these are needed to download the necessary artifacts for verification from AWS S3).
|
|
1828
|
-
verificationTranscriptTemporaryLocalPath = createTemporaryLocalPath(verificationTranscriptCompleteFilename);
|
|
1829
|
-
const potTempFilePath = createTemporaryLocalPath(`${circuitId}_${participantDoc.id}.pot`);
|
|
1830
|
-
const firstZkeyTempFilePath = createTemporaryLocalPath(`${circuitId}_${participantDoc.id}_genesis.zkey`);
|
|
1831
|
-
const lastZkeyTempFilePath = createTemporaryLocalPath(`${circuitId}_${participantDoc.id}_last.zkey`);
|
|
1832
|
-
// Create and populate transcript.
|
|
1833
|
-
const transcriptLogger = actions.createCustomLoggerForFile(verificationTranscriptTemporaryLocalPath);
|
|
1834
|
-
transcriptLogger.info(`${isFinalizing ? `Final verification` : `Verification`} transcript for ${prefix} circuit Phase 2 contribution.\n${isFinalizing ? `Coordinator ` : `Contributor # ${Number(lastZkeyIndex)}`} (${contributorOrCoordinatorIdentifier})\n`);
|
|
1835
|
-
// Step (1.A.2).
|
|
1836
|
-
await downloadArtifactFromS3Bucket(bucketName, potStoragePath, potTempFilePath);
|
|
1837
|
-
await downloadArtifactFromS3Bucket(bucketName, firstZkeyStoragePath, firstZkeyTempFilePath);
|
|
1838
|
-
await downloadArtifactFromS3Bucket(bucketName, lastZkeyStoragePath, lastZkeyTempFilePath);
|
|
1839
|
-
// Step (1.A.4).
|
|
1840
|
-
isContributionValid = await snarkjs.zKey.verifyFromInit(firstZkeyTempFilePath, potTempFilePath, lastZkeyTempFilePath, transcriptLogger);
|
|
1841
|
-
// Compute contribution hash.
|
|
1842
|
-
lastZkeyBlake2bHash = await actions.blake512FromPath(lastZkeyTempFilePath);
|
|
1843
|
-
// Free resources by unlinking temporary folders.
|
|
1844
|
-
// Do not free-up verification transcript path here.
|
|
1845
|
-
try {
|
|
1846
|
-
fs.unlinkSync(potTempFilePath);
|
|
1847
|
-
fs.unlinkSync(firstZkeyTempFilePath);
|
|
1848
|
-
fs.unlinkSync(lastZkeyTempFilePath);
|
|
1849
|
-
}
|
|
1850
|
-
catch (error) {
|
|
1851
|
-
printLog(`Error while unlinking temporary files - Error ${error}`, LogLevel.WARN);
|
|
1852
|
-
}
|
|
1853
|
-
await completeVerification();
|
|
1917
|
+
return null;
|
|
1918
|
+
}
|
|
1919
|
+
catch (error) {
|
|
1920
|
+
logAndThrowError(makeError("unknown", error));
|
|
1921
|
+
return null;
|
|
1854
1922
|
}
|
|
1855
1923
|
});
|
|
1856
1924
|
/**
|
|
@@ -1861,7 +1929,7 @@ const verifycontribution = functionsV2__namespace.https.onCall({ memory: "16GiB"
|
|
|
1861
1929
|
const refreshParticipantAfterContributionVerification = functionsV1__namespace
|
|
1862
1930
|
.region("europe-west1")
|
|
1863
1931
|
.runWith({
|
|
1864
|
-
memory: "
|
|
1932
|
+
memory: "1GB"
|
|
1865
1933
|
})
|
|
1866
1934
|
.firestore.document(`/${actions.commonTerms.collections.ceremonies.name}/{ceremony}/${actions.commonTerms.collections.circuits.name}/{circuit}/${actions.commonTerms.collections.contributions.name}/{contributions}`)
|
|
1867
1935
|
.onCreate(async (createdContribution) => {
|
|
@@ -1912,7 +1980,7 @@ const refreshParticipantAfterContributionVerification = functionsV1__namespace
|
|
|
1912
1980
|
lastUpdated: getCurrentServerTimestampInMillis()
|
|
1913
1981
|
});
|
|
1914
1982
|
await batch.commit();
|
|
1915
|
-
printLog(`Participant ${participantId} refreshed after contribution ${createdContribution.id} - The participant was finalizing the ceremony ${isFinalizing}`, LogLevel.
|
|
1983
|
+
printLog(`Participant ${participantId} refreshed after contribution ${createdContribution.id} - The participant was finalizing the ceremony? ${isFinalizing}`, LogLevel.INFO);
|
|
1916
1984
|
});
|
|
1917
1985
|
/**
|
|
1918
1986
|
* Finalize the ceremony circuit.
|
|
@@ -1922,7 +1990,7 @@ const refreshParticipantAfterContributionVerification = functionsV1__namespace
|
|
|
1922
1990
|
const finalizeCircuit = functionsV1__namespace
|
|
1923
1991
|
.region("europe-west1")
|
|
1924
1992
|
.runWith({
|
|
1925
|
-
memory: "
|
|
1993
|
+
memory: "1GB"
|
|
1926
1994
|
})
|
|
1927
1995
|
.https.onCall(async (data, context) => {
|
|
1928
1996
|
if (!context.auth || !context.auth.token.coordinator)
|
|
@@ -2066,7 +2134,7 @@ const checkIfBucketIsDedicatedToCeremony = async (bucketName) => {
|
|
|
2066
2134
|
const createBucket = functions__namespace
|
|
2067
2135
|
.region("europe-west1")
|
|
2068
2136
|
.runWith({
|
|
2069
|
-
memory: "
|
|
2137
|
+
memory: "1GB"
|
|
2070
2138
|
})
|
|
2071
2139
|
.https.onCall(async (data, context) => {
|
|
2072
2140
|
// Check if the user has the coordinator claim.
|
|
@@ -2077,6 +2145,7 @@ const createBucket = functions__namespace
|
|
|
2077
2145
|
// Connect to S3 client.
|
|
2078
2146
|
const S3 = await getS3Client();
|
|
2079
2147
|
try {
|
|
2148
|
+
printLog(`Creating AWS S3 bucket ${data.bucketName} ...`, LogLevel.LOG);
|
|
2080
2149
|
// Try to get information about the bucket.
|
|
2081
2150
|
await S3.send(new clientS3.HeadBucketCommand({ Bucket: data.bucketName }));
|
|
2082
2151
|
// If the command succeeded, the bucket exists, throw an error.
|
|
@@ -2156,7 +2225,7 @@ const createBucket = functions__namespace
|
|
|
2156
2225
|
const checkIfObjectExist = functions__namespace
|
|
2157
2226
|
.region("europe-west1")
|
|
2158
2227
|
.runWith({
|
|
2159
|
-
memory: "
|
|
2228
|
+
memory: "1GB"
|
|
2160
2229
|
})
|
|
2161
2230
|
.https.onCall(async (data, context) => {
|
|
2162
2231
|
// Check if the user has the coordinator claim.
|
|
@@ -2202,7 +2271,7 @@ const checkIfObjectExist = functions__namespace
|
|
|
2202
2271
|
const generateGetObjectPreSignedUrl = functions__namespace
|
|
2203
2272
|
.region("europe-west1")
|
|
2204
2273
|
.runWith({
|
|
2205
|
-
memory: "
|
|
2274
|
+
memory: "1GB"
|
|
2206
2275
|
})
|
|
2207
2276
|
.https.onCall(async (data, context) => {
|
|
2208
2277
|
if (!context.auth)
|
|
@@ -2242,7 +2311,7 @@ const generateGetObjectPreSignedUrl = functions__namespace
|
|
|
2242
2311
|
const startMultiPartUpload = functions__namespace
|
|
2243
2312
|
.region("europe-west1")
|
|
2244
2313
|
.runWith({
|
|
2245
|
-
memory: "
|
|
2314
|
+
memory: "2GB"
|
|
2246
2315
|
})
|
|
2247
2316
|
.https.onCall(async (data, context) => {
|
|
2248
2317
|
if (!context.auth || (!context.auth.token.participant && !context.auth.token.coordinator))
|
|
@@ -2297,7 +2366,7 @@ const startMultiPartUpload = functions__namespace
|
|
|
2297
2366
|
const generatePreSignedUrlsParts = functions__namespace
|
|
2298
2367
|
.region("europe-west1")
|
|
2299
2368
|
.runWith({
|
|
2300
|
-
memory: "
|
|
2369
|
+
memory: "1GB",
|
|
2301
2370
|
timeoutSeconds: 300
|
|
2302
2371
|
})
|
|
2303
2372
|
.https.onCall(async (data, context) => {
|
|
@@ -2358,7 +2427,7 @@ const generatePreSignedUrlsParts = functions__namespace
|
|
|
2358
2427
|
const completeMultiPartUpload = functions__namespace
|
|
2359
2428
|
.region("europe-west1")
|
|
2360
2429
|
.runWith({
|
|
2361
|
-
memory: "
|
|
2430
|
+
memory: "2GB"
|
|
2362
2431
|
})
|
|
2363
2432
|
.https.onCall(async (data, context) => {
|
|
2364
2433
|
if (!context.auth || (!context.auth.token.participant && !context.auth.token.coordinator))
|
|
@@ -2407,6 +2476,216 @@ const completeMultiPartUpload = functions__namespace
|
|
|
2407
2476
|
}
|
|
2408
2477
|
});
|
|
2409
2478
|
|
|
2479
|
+
dotenv.config();
|
|
2480
|
+
const { BANDADA_API_URL, BANDADA_GROUP_ID } = process.env;
|
|
2481
|
+
const bandadaApi = new apiSdk.ApiSdk(BANDADA_API_URL);
|
|
2482
|
+
const bandadaValidateProof = functions__namespace
|
|
2483
|
+
.region("europe-west1")
|
|
2484
|
+
.runWith({
|
|
2485
|
+
memory: "1GB"
|
|
2486
|
+
})
|
|
2487
|
+
.https.onCall(async (data) => {
|
|
2488
|
+
const VKEY_DATA = {
|
|
2489
|
+
protocol: "groth16",
|
|
2490
|
+
curve: "bn128",
|
|
2491
|
+
nPublic: 3,
|
|
2492
|
+
vk_alpha_1: [
|
|
2493
|
+
"20491192805390485299153009773594534940189261866228447918068658471970481763042",
|
|
2494
|
+
"9383485363053290200918347156157836566562967994039712273449902621266178545958",
|
|
2495
|
+
"1"
|
|
2496
|
+
],
|
|
2497
|
+
vk_beta_2: [
|
|
2498
|
+
[
|
|
2499
|
+
"6375614351688725206403948262868962793625744043794305715222011528459656738731",
|
|
2500
|
+
"4252822878758300859123897981450591353533073413197771768651442665752259397132"
|
|
2501
|
+
],
|
|
2502
|
+
[
|
|
2503
|
+
"10505242626370262277552901082094356697409835680220590971873171140371331206856",
|
|
2504
|
+
"21847035105528745403288232691147584728191162732299865338377159692350059136679"
|
|
2505
|
+
],
|
|
2506
|
+
["1", "0"]
|
|
2507
|
+
],
|
|
2508
|
+
vk_gamma_2: [
|
|
2509
|
+
[
|
|
2510
|
+
"10857046999023057135944570762232829481370756359578518086990519993285655852781",
|
|
2511
|
+
"11559732032986387107991004021392285783925812861821192530917403151452391805634"
|
|
2512
|
+
],
|
|
2513
|
+
[
|
|
2514
|
+
"8495653923123431417604973247489272438418190587263600148770280649306958101930",
|
|
2515
|
+
"4082367875863433681332203403145435568316851327593401208105741076214120093531"
|
|
2516
|
+
],
|
|
2517
|
+
["1", "0"]
|
|
2518
|
+
],
|
|
2519
|
+
vk_delta_2: [
|
|
2520
|
+
[
|
|
2521
|
+
"3697618915467790705869942236922063775466274665053173890632463796679068973252",
|
|
2522
|
+
"14948341351907992175709156460547989243732741534604949238422596319735704165658"
|
|
2523
|
+
],
|
|
2524
|
+
[
|
|
2525
|
+
"3028459181652799888716942141752307629938889957960373621898607910203491239368",
|
|
2526
|
+
"11380736494786911280692284374675752681598754560757720296073023058533044108340"
|
|
2527
|
+
],
|
|
2528
|
+
["1", "0"]
|
|
2529
|
+
],
|
|
2530
|
+
vk_alphabeta_12: [
|
|
2531
|
+
[
|
|
2532
|
+
[
|
|
2533
|
+
"2029413683389138792403550203267699914886160938906632433982220835551125967885",
|
|
2534
|
+
"21072700047562757817161031222997517981543347628379360635925549008442030252106"
|
|
2535
|
+
],
|
|
2536
|
+
[
|
|
2537
|
+
"5940354580057074848093997050200682056184807770593307860589430076672439820312",
|
|
2538
|
+
"12156638873931618554171829126792193045421052652279363021382169897324752428276"
|
|
2539
|
+
],
|
|
2540
|
+
[
|
|
2541
|
+
"7898200236362823042373859371574133993780991612861777490112507062703164551277",
|
|
2542
|
+
"7074218545237549455313236346927434013100842096812539264420499035217050630853"
|
|
2543
|
+
]
|
|
2544
|
+
],
|
|
2545
|
+
[
|
|
2546
|
+
[
|
|
2547
|
+
"7077479683546002997211712695946002074877511277312570035766170199895071832130",
|
|
2548
|
+
"10093483419865920389913245021038182291233451549023025229112148274109565435465"
|
|
2549
|
+
],
|
|
2550
|
+
[
|
|
2551
|
+
"4595479056700221319381530156280926371456704509942304414423590385166031118820",
|
|
2552
|
+
"19831328484489333784475432780421641293929726139240675179672856274388269393268"
|
|
2553
|
+
],
|
|
2554
|
+
[
|
|
2555
|
+
"11934129596455521040620786944827826205713621633706285934057045369193958244500",
|
|
2556
|
+
"8037395052364110730298837004334506829870972346962140206007064471173334027475"
|
|
2557
|
+
]
|
|
2558
|
+
]
|
|
2559
|
+
],
|
|
2560
|
+
IC: [
|
|
2561
|
+
[
|
|
2562
|
+
"12951059800758687233303204819298121944551181861362200875212570257618182506154",
|
|
2563
|
+
"5751958719396509176593242305268064754837298673622815112953832050159760501392",
|
|
2564
|
+
"1"
|
|
2565
|
+
],
|
|
2566
|
+
[
|
|
2567
|
+
"9561588427935871983444704959674198910445823619407211599507208879011862515257",
|
|
2568
|
+
"14576201570478094842467636169770180675293504492823217349086195663150934064643",
|
|
2569
|
+
"1"
|
|
2570
|
+
],
|
|
2571
|
+
[
|
|
2572
|
+
"4811967233483727873912563574622036989372099129165459921963463310078093941559",
|
|
2573
|
+
"1874883809855039536107616044787862082553628089593740724610117059083415551067",
|
|
2574
|
+
"1"
|
|
2575
|
+
],
|
|
2576
|
+
[
|
|
2577
|
+
"12252730267779308452229639835051322390696643456253768618882001876621526827161",
|
|
2578
|
+
"7899194018737016222260328309937800777948677569409898603827268776967707173231",
|
|
2579
|
+
"1"
|
|
2580
|
+
]
|
|
2581
|
+
]
|
|
2582
|
+
};
|
|
2583
|
+
if (!BANDADA_GROUP_ID)
|
|
2584
|
+
throw new Error("BANDADA_GROUP_ID is not defined in .env");
|
|
2585
|
+
const { proof, publicSignals } = data;
|
|
2586
|
+
const isCorrect = snarkjs.groth16.verify(VKEY_DATA, publicSignals, proof);
|
|
2587
|
+
if (!isCorrect)
|
|
2588
|
+
return {
|
|
2589
|
+
valid: false,
|
|
2590
|
+
message: "Invalid proof",
|
|
2591
|
+
token: ""
|
|
2592
|
+
};
|
|
2593
|
+
const commitment = data.publicSignals[1];
|
|
2594
|
+
const isMember = await bandadaApi.isGroupMember(BANDADA_GROUP_ID, commitment);
|
|
2595
|
+
if (!isMember)
|
|
2596
|
+
return {
|
|
2597
|
+
valid: false,
|
|
2598
|
+
message: "Not a member of the group",
|
|
2599
|
+
token: ""
|
|
2600
|
+
};
|
|
2601
|
+
const auth$1 = auth.getAuth();
|
|
2602
|
+
try {
|
|
2603
|
+
await admin.auth().createUser({
|
|
2604
|
+
uid: commitment
|
|
2605
|
+
});
|
|
2606
|
+
}
|
|
2607
|
+
catch (error) {
|
|
2608
|
+
// if user already exist then just pass
|
|
2609
|
+
if (error.code !== "auth/uid-already-exists") {
|
|
2610
|
+
throw new Error(error);
|
|
2611
|
+
}
|
|
2612
|
+
}
|
|
2613
|
+
const token = await auth$1.createCustomToken(commitment);
|
|
2614
|
+
return {
|
|
2615
|
+
valid: true,
|
|
2616
|
+
message: "Valid proof and group member",
|
|
2617
|
+
token
|
|
2618
|
+
};
|
|
2619
|
+
});
|
|
2620
|
+
|
|
2621
|
+
dotenv.config();
|
|
2622
|
+
const checkNonceOfSIWEAddress = functions__namespace
|
|
2623
|
+
.region("europe-west1")
|
|
2624
|
+
.runWith({ memory: "1GB" })
|
|
2625
|
+
.https.onCall(async (data) => {
|
|
2626
|
+
try {
|
|
2627
|
+
const { auth0Token } = data;
|
|
2628
|
+
const result = (await fetch(`${process.env.AUTH0_APPLICATION_URL}/userinfo`, {
|
|
2629
|
+
method: "GET",
|
|
2630
|
+
headers: {
|
|
2631
|
+
"content-type": "application/json",
|
|
2632
|
+
authorization: `Bearer ${auth0Token}`
|
|
2633
|
+
}
|
|
2634
|
+
}).then((_res) => _res.json()));
|
|
2635
|
+
if (!result.sub) {
|
|
2636
|
+
return {
|
|
2637
|
+
valid: false,
|
|
2638
|
+
message: "No user detected. Please check device flow token"
|
|
2639
|
+
};
|
|
2640
|
+
}
|
|
2641
|
+
const auth$1 = auth.getAuth();
|
|
2642
|
+
// check nonce
|
|
2643
|
+
const parts = result.sub.split("|");
|
|
2644
|
+
const address = decodeURIComponent(parts[2]).split(":")[2];
|
|
2645
|
+
const minimumNonce = Number(process.env.ETH_MINIMUM_NONCE);
|
|
2646
|
+
const nonceBlockHeight = "latest"; // process.env.ETH_NONCE_BLOCK_HEIGHT
|
|
2647
|
+
// look up nonce for address @block
|
|
2648
|
+
let nonceOk = true;
|
|
2649
|
+
if (minimumNonce > 0) {
|
|
2650
|
+
const provider = setEthProvider();
|
|
2651
|
+
console.log(`got provider - block # ${await provider.getBlockNumber()}`);
|
|
2652
|
+
const nonce = await provider.getTransactionCount(address, nonceBlockHeight);
|
|
2653
|
+
console.log(`nonce ${nonce}`);
|
|
2654
|
+
nonceOk = nonce >= minimumNonce;
|
|
2655
|
+
}
|
|
2656
|
+
console.log(`checking nonce ${nonceOk}`);
|
|
2657
|
+
if (!nonceOk) {
|
|
2658
|
+
return {
|
|
2659
|
+
valid: false,
|
|
2660
|
+
message: "Eth address does not meet the nonce requirements"
|
|
2661
|
+
};
|
|
2662
|
+
}
|
|
2663
|
+
try {
|
|
2664
|
+
await admin.auth().createUser({
|
|
2665
|
+
displayName: address,
|
|
2666
|
+
uid: address
|
|
2667
|
+
});
|
|
2668
|
+
}
|
|
2669
|
+
catch (error) {
|
|
2670
|
+
// if user already exist then just pass
|
|
2671
|
+
if (error.code !== "auth/uid-already-exists") {
|
|
2672
|
+
throw new Error(error);
|
|
2673
|
+
}
|
|
2674
|
+
}
|
|
2675
|
+
const token = await auth$1.createCustomToken(address);
|
|
2676
|
+
return {
|
|
2677
|
+
valid: true,
|
|
2678
|
+
token
|
|
2679
|
+
};
|
|
2680
|
+
}
|
|
2681
|
+
catch (error) {
|
|
2682
|
+
return {
|
|
2683
|
+
valid: false,
|
|
2684
|
+
message: `Something went wrong ${error}`
|
|
2685
|
+
};
|
|
2686
|
+
}
|
|
2687
|
+
});
|
|
2688
|
+
|
|
2410
2689
|
dotenv.config();
|
|
2411
2690
|
/**
|
|
2412
2691
|
* Check and remove the current contributor if it doesn't complete the contribution on the specified amount of time.
|
|
@@ -2429,7 +2708,7 @@ dotenv.config();
|
|
|
2429
2708
|
const checkAndRemoveBlockingContributor = functions__namespace
|
|
2430
2709
|
.region("europe-west1")
|
|
2431
2710
|
.runWith({
|
|
2432
|
-
memory: "
|
|
2711
|
+
memory: "1GB"
|
|
2433
2712
|
})
|
|
2434
2713
|
.pubsub.schedule("every 1 minutes")
|
|
2435
2714
|
.onRun(async () => {
|
|
@@ -2448,7 +2727,7 @@ const checkAndRemoveBlockingContributor = functions__namespace
|
|
|
2448
2727
|
// Get ceremony circuits.
|
|
2449
2728
|
const circuits = await getCeremonyCircuits(ceremony.id);
|
|
2450
2729
|
// Extract ceremony data.
|
|
2451
|
-
const { timeoutMechanismType, penalty } = ceremony.data();
|
|
2730
|
+
const { timeoutType: timeoutMechanismType, penalty } = ceremony.data();
|
|
2452
2731
|
for (const circuit of circuits) {
|
|
2453
2732
|
if (!circuit.data())
|
|
2454
2733
|
// Do not use `logAndThrowError` method to avoid the function to exit before checking every ceremony.
|
|
@@ -2461,7 +2740,7 @@ const checkAndRemoveBlockingContributor = functions__namespace
|
|
|
2461
2740
|
// Case (A).
|
|
2462
2741
|
if (!currentContributor)
|
|
2463
2742
|
// Do not use `logAndThrowError` method to avoid the function to exit before checking every ceremony.
|
|
2464
|
-
printLog(`No current contributor for circuit ${circuit.id} - ceremony ${ceremony.id}`, LogLevel.
|
|
2743
|
+
printLog(`No current contributor for circuit ${circuit.id} - ceremony ${ceremony.id}`, LogLevel.DEBUG);
|
|
2465
2744
|
else if (avgFullContribution === 0 &&
|
|
2466
2745
|
avgContributionComputation === 0 &&
|
|
2467
2746
|
avgVerifyCloudFunction === 0 &&
|
|
@@ -2487,7 +2766,7 @@ const checkAndRemoveBlockingContributor = functions__namespace
|
|
|
2487
2766
|
? Number(contributionStartedAt) +
|
|
2488
2767
|
Number(avgFullContribution) +
|
|
2489
2768
|
Number(timeoutDynamicThreshold)
|
|
2490
|
-
: Number(contributionStartedAt) + Number(fixedTimeWindow) * 60000; // * 60000 = convert minutes to millis.
|
|
2769
|
+
: (Number(contributionStartedAt) + Number(fixedTimeWindow)) * 60000; // * 60000 = convert minutes to millis.
|
|
2491
2770
|
// Case (D).
|
|
2492
2771
|
const timeoutExpirationDateInMsForVerificationCloudFunction = contributionStep === "VERIFYING" /* ParticipantContributionStep.VERIFYING */ &&
|
|
2493
2772
|
!!verificationStartedAt
|
|
@@ -2498,17 +2777,18 @@ const checkAndRemoveBlockingContributor = functions__namespace
|
|
|
2498
2777
|
if (timeoutExpirationDateInMsForBlockingContributor < currentServerTimestamp &&
|
|
2499
2778
|
(contributionStep === "DOWNLOADING" /* ParticipantContributionStep.DOWNLOADING */ ||
|
|
2500
2779
|
contributionStep === "COMPUTING" /* ParticipantContributionStep.COMPUTING */ ||
|
|
2501
|
-
contributionStep === "UPLOADING" /* ParticipantContributionStep.UPLOADING */
|
|
2780
|
+
contributionStep === "UPLOADING" /* ParticipantContributionStep.UPLOADING */ ||
|
|
2781
|
+
contributionStep === "COMPLETED" /* ParticipantContributionStep.COMPLETED */))
|
|
2502
2782
|
timeoutType = "BLOCKING_CONTRIBUTION" /* TimeoutType.BLOCKING_CONTRIBUTION */;
|
|
2503
2783
|
if (timeoutExpirationDateInMsForVerificationCloudFunction > 0 &&
|
|
2504
2784
|
timeoutExpirationDateInMsForVerificationCloudFunction < currentServerTimestamp &&
|
|
2505
2785
|
contributionStep === "VERIFYING" /* ParticipantContributionStep.VERIFYING */)
|
|
2506
2786
|
timeoutType = "BLOCKING_CLOUD_FUNCTION" /* TimeoutType.BLOCKING_CLOUD_FUNCTION */;
|
|
2507
|
-
printLog(`${timeoutType} detected for circuit ${circuit.id} - ceremony ${ceremony.id}`, LogLevel.DEBUG);
|
|
2508
2787
|
if (!timeoutType)
|
|
2509
2788
|
// Do not use `logAndThrowError` method to avoid the function to exit before checking every ceremony.
|
|
2510
|
-
printLog(`No timeout for circuit ${circuit.id} - ceremony ${ceremony.id}`, LogLevel.
|
|
2789
|
+
printLog(`No timeout for circuit ${circuit.id} - ceremony ${ceremony.id}`, LogLevel.DEBUG);
|
|
2511
2790
|
else {
|
|
2791
|
+
printLog(`${timeoutType} detected for circuit ${circuit.id} - ceremony ${ceremony.id}`, LogLevel.WARN);
|
|
2512
2792
|
// Case (E).
|
|
2513
2793
|
let nextCurrentContributorId = "";
|
|
2514
2794
|
// Prepare Firestore batch of txs.
|
|
@@ -2559,7 +2839,7 @@ const checkAndRemoveBlockingContributor = functions__namespace
|
|
|
2559
2839
|
});
|
|
2560
2840
|
// Send atomic update for Firestore.
|
|
2561
2841
|
await batch.commit();
|
|
2562
|
-
printLog(`The contributor ${participant.id} has been identified as potential blocking contributor. A timeout of type ${timeoutType} has been triggered w/ a penalty of ${timeoutPenaltyInMs} ms`, LogLevel.
|
|
2842
|
+
printLog(`The contributor ${participant.id} has been identified as potential blocking contributor. A timeout of type ${timeoutType} has been triggered w/ a penalty of ${timeoutPenaltyInMs} ms`, LogLevel.WARN);
|
|
2563
2843
|
}
|
|
2564
2844
|
}
|
|
2565
2845
|
}
|
|
@@ -2575,7 +2855,7 @@ const checkAndRemoveBlockingContributor = functions__namespace
|
|
|
2575
2855
|
const resumeContributionAfterTimeoutExpiration = functions__namespace
|
|
2576
2856
|
.region("europe-west1")
|
|
2577
2857
|
.runWith({
|
|
2578
|
-
memory: "
|
|
2858
|
+
memory: "1GB"
|
|
2579
2859
|
})
|
|
2580
2860
|
.https.onCall(async (data, context) => {
|
|
2581
2861
|
if (!context.auth || (!context.auth.token.participant && !context.auth.token.coordinator))
|
|
@@ -2608,9 +2888,11 @@ const resumeContributionAfterTimeoutExpiration = functions__namespace
|
|
|
2608
2888
|
|
|
2609
2889
|
admin.initializeApp();
|
|
2610
2890
|
|
|
2891
|
+
exports.bandadaValidateProof = bandadaValidateProof;
|
|
2611
2892
|
exports.checkAndPrepareCoordinatorForFinalization = checkAndPrepareCoordinatorForFinalization;
|
|
2612
2893
|
exports.checkAndRemoveBlockingContributor = checkAndRemoveBlockingContributor;
|
|
2613
2894
|
exports.checkIfObjectExist = checkIfObjectExist;
|
|
2895
|
+
exports.checkNonceOfSIWEAddress = checkNonceOfSIWEAddress;
|
|
2614
2896
|
exports.checkParticipantForCeremony = checkParticipantForCeremony;
|
|
2615
2897
|
exports.completeMultiPartUpload = completeMultiPartUpload;
|
|
2616
2898
|
exports.coordinateCeremonyParticipant = coordinateCeremonyParticipant;
|