@devtion/backend 0.0.0-92056fa → 0.0.0-9843891
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 +413 -129
- package/dist/src/functions/index.mjs +416 -134
- 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 +2 -0
- package/dist/types/functions/index.d.ts.map +1 -1
- package/dist/types/functions/siwe.d.ts +4 -0
- package/dist/types/functions/siwe.d.ts.map +1 -0
- 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/services.d.ts +7 -0
- package/dist/types/lib/services.d.ts.map +1 -1
- package/dist/types/lib/utils.d.ts.map +1 -1
- package/dist/types/types/index.d.ts +56 -0
- package/dist/types/types/index.d.ts.map +1 -1
- package/package.json +4 -3
- package/src/functions/bandada.ts +155 -0
- package/src/functions/ceremony.ts +11 -6
- package/src/functions/circuit.ts +140 -118
- package/src/functions/index.ts +2 -0
- package/src/functions/participant.ts +15 -15
- package/src/functions/siwe.ts +77 -0
- package/src/functions/storage.ts +11 -8
- package/src/functions/timeout.ts +7 -5
- package/src/functions/user.ts +22 -12
- package/src/lib/errors.ts +6 -1
- package/src/lib/services.ts +36 -0
- package/src/lib/utils.ts +10 -8
- package/src/types/declarations.d.ts +1 -0
- package/src/types/index.ts +60 -0
package/src/functions/circuit.ts
CHANGED
|
@@ -40,9 +40,11 @@ import {
|
|
|
40
40
|
} from "@devtion/actions"
|
|
41
41
|
import { zKey } from "snarkjs"
|
|
42
42
|
import { CommandInvocationStatus, SSMClient } from "@aws-sdk/client-ssm"
|
|
43
|
+
import { EC2Client } from "@aws-sdk/client-ec2"
|
|
44
|
+
import { HttpsError } from "firebase-functions/v2/https"
|
|
43
45
|
import { FinalizeCircuitData, VerifyContributionData } from "../types/index"
|
|
44
46
|
import { LogLevel } from "../types/enums"
|
|
45
|
-
import { COMMON_ERRORS, logAndThrowError,
|
|
47
|
+
import { COMMON_ERRORS, logAndThrowError, printLog, SPECIFIC_ERRORS } from "../lib/errors"
|
|
46
48
|
import {
|
|
47
49
|
createEC2Client,
|
|
48
50
|
createSSMClient,
|
|
@@ -57,7 +59,6 @@ import {
|
|
|
57
59
|
sleep,
|
|
58
60
|
uploadFileToBucket
|
|
59
61
|
} from "../lib/utils"
|
|
60
|
-
import { EC2Client } from "@aws-sdk/client-ec2"
|
|
61
62
|
|
|
62
63
|
dotenv.config()
|
|
63
64
|
|
|
@@ -214,57 +215,80 @@ const coordinate = async (
|
|
|
214
215
|
* Wait until the command has completed its execution inside the VM.
|
|
215
216
|
* @dev this method implements a custom interval to check 5 times after 1 minute if the command execution
|
|
216
217
|
* has been completed or not by calling the `retrieveCommandStatus` method.
|
|
217
|
-
* @param {any} resolve the promise.
|
|
218
|
-
* @param {any} reject the promise.
|
|
219
218
|
* @param {SSMClient} ssm the SSM client.
|
|
220
219
|
* @param {string} vmInstanceId the unique identifier of the VM instance.
|
|
221
220
|
* @param {string} commandId the unique identifier of the VM command.
|
|
222
221
|
* @returns <Promise<void>> true when the command execution succeed; otherwise false.
|
|
223
222
|
*/
|
|
224
|
-
const waitForVMCommandExecution = (
|
|
225
|
-
resolve
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
223
|
+
const waitForVMCommandExecution = (ssm: SSMClient, vmInstanceId: string, commandId: string): Promise<void> =>
|
|
224
|
+
new Promise((resolve, reject) => {
|
|
225
|
+
const poll = async () => {
|
|
226
|
+
try {
|
|
227
|
+
// Get command status.
|
|
228
|
+
const cmdStatus = await retrieveCommandStatus(ssm, vmInstanceId, commandId)
|
|
229
|
+
printLog(`Checking command ${commandId} status => ${cmdStatus}`, LogLevel.DEBUG)
|
|
230
|
+
|
|
231
|
+
let error: HttpsError | undefined
|
|
232
|
+
switch (cmdStatus) {
|
|
233
|
+
case CommandInvocationStatus.CANCELLING:
|
|
234
|
+
case CommandInvocationStatus.CANCELLED: {
|
|
235
|
+
error = SPECIFIC_ERRORS.SE_VM_CANCELLED_COMMAND_EXECUTION
|
|
236
|
+
break
|
|
237
|
+
}
|
|
238
|
+
case CommandInvocationStatus.DELAYED: {
|
|
239
|
+
error = SPECIFIC_ERRORS.SE_VM_DELAYED_COMMAND_EXECUTION
|
|
240
|
+
break
|
|
241
|
+
}
|
|
242
|
+
case CommandInvocationStatus.FAILED: {
|
|
243
|
+
error = SPECIFIC_ERRORS.SE_VM_FAILED_COMMAND_EXECUTION
|
|
244
|
+
break
|
|
245
|
+
}
|
|
246
|
+
case CommandInvocationStatus.TIMED_OUT: {
|
|
247
|
+
error = SPECIFIC_ERRORS.SE_VM_TIMEDOUT_COMMAND_EXECUTION
|
|
248
|
+
break
|
|
249
|
+
}
|
|
250
|
+
case CommandInvocationStatus.IN_PROGRESS:
|
|
251
|
+
case CommandInvocationStatus.PENDING: {
|
|
252
|
+
// wait a minute and poll again
|
|
253
|
+
setTimeout(poll, 60000)
|
|
254
|
+
return
|
|
255
|
+
}
|
|
256
|
+
case CommandInvocationStatus.SUCCESS: {
|
|
257
|
+
printLog(`Command ${commandId} successfully completed`, LogLevel.DEBUG)
|
|
258
|
+
|
|
259
|
+
// Resolve the promise.
|
|
260
|
+
resolve()
|
|
261
|
+
return
|
|
262
|
+
}
|
|
263
|
+
default: {
|
|
264
|
+
logAndThrowError(SPECIFIC_ERRORS.SE_VM_UNKNOWN_COMMAND_STATUS)
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
if (error) {
|
|
269
|
+
logAndThrowError(error)
|
|
270
|
+
}
|
|
271
|
+
} catch (error: any) {
|
|
272
|
+
printLog(`Invalid command ${commandId} execution`, LogLevel.DEBUG)
|
|
257
273
|
|
|
258
|
-
|
|
274
|
+
const ec2 = await createEC2Client()
|
|
259
275
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
276
|
+
// if it errors out, let's just log it as a warning so the coordinator is aware
|
|
277
|
+
try {
|
|
278
|
+
await stopEC2Instance(ec2, vmInstanceId)
|
|
279
|
+
} catch (error: any) {
|
|
280
|
+
printLog(`Error while stopping VM instance ${vmInstanceId} - Error ${error}`, LogLevel.WARN)
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
if (!error.toString().includes(commandId)) logAndThrowError(COMMON_ERRORS.CM_INVALID_COMMAND_EXECUTION)
|
|
284
|
+
|
|
285
|
+
// Reject the promise.
|
|
286
|
+
reject()
|
|
287
|
+
}
|
|
265
288
|
}
|
|
266
|
-
|
|
267
|
-
|
|
289
|
+
|
|
290
|
+
setTimeout(poll, 60000)
|
|
291
|
+
})
|
|
268
292
|
|
|
269
293
|
/**
|
|
270
294
|
* This method is used to coordinate the waiting queues of ceremony circuits.
|
|
@@ -286,9 +310,9 @@ const waitForVMCommandExecution = (
|
|
|
286
310
|
* - Just completed a contribution or all contributions for each circuit. If yes, coordinate (multi-participant scenario).
|
|
287
311
|
*/
|
|
288
312
|
export const coordinateCeremonyParticipant = functionsV1
|
|
289
|
-
.region(
|
|
313
|
+
.region("europe-west1")
|
|
290
314
|
.runWith({
|
|
291
|
-
memory: "
|
|
315
|
+
memory: "1GB"
|
|
292
316
|
})
|
|
293
317
|
.firestore.document(
|
|
294
318
|
`${commonTerms.collections.ceremonies.name}/{ceremonyId}/${commonTerms.collections.participants.name}/{participantId}`
|
|
@@ -387,7 +411,6 @@ export const coordinateCeremonyParticipant = functionsV1
|
|
|
387
411
|
}
|
|
388
412
|
})
|
|
389
413
|
|
|
390
|
-
|
|
391
414
|
/**
|
|
392
415
|
* Recursive function to check whether an EC2 is in a running state
|
|
393
416
|
* @notice required step to run commands
|
|
@@ -396,23 +419,18 @@ export const coordinateCeremonyParticipant = functionsV1
|
|
|
396
419
|
* @param attempts <number> - how many times to retry before failing
|
|
397
420
|
* @returns <Promise<boolean>> - whether the VM was started
|
|
398
421
|
*/
|
|
399
|
-
const checkIfVMRunning = async (
|
|
400
|
-
ec2: EC2Client,
|
|
401
|
-
vmInstanceId: string,
|
|
402
|
-
attempts = 5
|
|
403
|
-
): Promise<boolean> => {
|
|
422
|
+
const checkIfVMRunning = async (ec2: EC2Client, vmInstanceId: string, attempts = 5): Promise<boolean> => {
|
|
404
423
|
// if we tried 5 times, then throw an error
|
|
405
424
|
if (attempts <= 0) logAndThrowError(SPECIFIC_ERRORS.SE_VM_NOT_RUNNING)
|
|
406
425
|
|
|
407
|
-
await sleep(60000)
|
|
408
|
-
const isVMRunning = await checkIfRunning(ec2, vmInstanceId)
|
|
426
|
+
await sleep(60000) // Wait for 1 min
|
|
427
|
+
const isVMRunning = await checkIfRunning(ec2, vmInstanceId)
|
|
409
428
|
|
|
410
429
|
if (!isVMRunning) {
|
|
411
430
|
printLog(`VM not running, ${attempts - 1} attempts remaining. Retrying in 1 minute...`, LogLevel.DEBUG)
|
|
412
|
-
return
|
|
413
|
-
} else {
|
|
414
|
-
return true
|
|
431
|
+
return checkIfVMRunning(ec2, vmInstanceId, attempts - 1)
|
|
415
432
|
}
|
|
433
|
+
return true
|
|
416
434
|
}
|
|
417
435
|
|
|
418
436
|
/**
|
|
@@ -442,7 +460,7 @@ const checkIfVMRunning = async (
|
|
|
442
460
|
* 2) Send all updates atomically to the Firestore database.
|
|
443
461
|
*/
|
|
444
462
|
export const verifycontribution = functionsV2.https.onCall(
|
|
445
|
-
{ memory: "16GiB", timeoutSeconds: 3600, region:
|
|
463
|
+
{ memory: "16GiB", timeoutSeconds: 3600, region: "europe-west1" },
|
|
446
464
|
async (request: functionsV2.https.CallableRequest<VerifyContributionData>): Promise<any> => {
|
|
447
465
|
if (!request.auth || (!request.auth.token.participant && !request.auth.token.coordinator))
|
|
448
466
|
logAndThrowError(SPECIFIC_ERRORS.SE_AUTH_NO_CURRENT_AUTH_USER)
|
|
@@ -610,9 +628,6 @@ export const verifycontribution = functionsV2.https.onCall(
|
|
|
610
628
|
verificationTranscriptTemporaryLocalPath,
|
|
611
629
|
true
|
|
612
630
|
)
|
|
613
|
-
|
|
614
|
-
// Stop VM instance.
|
|
615
|
-
await stopEC2Instance(ec2, vmInstanceId)
|
|
616
631
|
} else {
|
|
617
632
|
// Upload verification transcript.
|
|
618
633
|
/// nb. do not use multi-part upload here due to small file size.
|
|
@@ -689,6 +704,17 @@ export const verifycontribution = functionsV2.https.onCall(
|
|
|
689
704
|
})
|
|
690
705
|
}
|
|
691
706
|
|
|
707
|
+
// Stop VM instance
|
|
708
|
+
if (isUsingVM) {
|
|
709
|
+
// using try and catch as the VM stopping function can throw
|
|
710
|
+
// however we want to continue without stopping as the
|
|
711
|
+
// verification was valid, and inform the coordinator
|
|
712
|
+
try {
|
|
713
|
+
await stopEC2Instance(ec2, vmInstanceId)
|
|
714
|
+
} catch (error: any) {
|
|
715
|
+
printLog(`Error while stopping VM instance ${vmInstanceId} - Error ${error}`, LogLevel.WARN)
|
|
716
|
+
}
|
|
717
|
+
}
|
|
692
718
|
// Step (1.A.4.C)
|
|
693
719
|
if (!isFinalizing) {
|
|
694
720
|
// Step (1.A.4.C.1)
|
|
@@ -708,7 +734,7 @@ export const verifycontribution = functionsV2.https.onCall(
|
|
|
708
734
|
? (avgVerifyCloudFunctionTime + verifyCloudFunctionTime) / 2
|
|
709
735
|
: verifyCloudFunctionTime
|
|
710
736
|
|
|
711
|
-
// Prepare tx to update circuit average contribution/verification time.
|
|
737
|
+
// Prepare tx to update circuit average contribution/verification time.
|
|
712
738
|
const updatedCircuitDoc = await getDocumentById(getCircuitsCollectionPath(ceremonyId), circuitId)
|
|
713
739
|
const { waitingQueue: updatedWaitingQueue } = updatedCircuitDoc.data()!
|
|
714
740
|
/// @dev this must happen only for valid contributions.
|
|
@@ -782,9 +808,7 @@ export const verifycontribution = functionsV2.https.onCall(
|
|
|
782
808
|
printLog(`Starting the execution of command ${commandId}`, LogLevel.DEBUG)
|
|
783
809
|
|
|
784
810
|
// Step (1.A.3.3).
|
|
785
|
-
return
|
|
786
|
-
waitForVMCommandExecution(resolve, reject, ssm, vmInstanceId, commandId)
|
|
787
|
-
)
|
|
811
|
+
return waitForVMCommandExecution(ssm, vmInstanceId, commandId)
|
|
788
812
|
.then(async () => {
|
|
789
813
|
// Command execution successfully completed.
|
|
790
814
|
printLog(`Command ${commandId} execution has been successfully completed`, LogLevel.DEBUG)
|
|
@@ -796,59 +820,57 @@ export const verifycontribution = functionsV2.https.onCall(
|
|
|
796
820
|
|
|
797
821
|
logAndThrowError(COMMON_ERRORS.CM_INVALID_COMMAND_EXECUTION)
|
|
798
822
|
})
|
|
799
|
-
}
|
|
800
|
-
// CF approach.
|
|
801
|
-
printLog(`CF mechanism`, LogLevel.DEBUG)
|
|
823
|
+
}
|
|
802
824
|
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
)
|
|
825
|
+
// CF approach.
|
|
826
|
+
printLog(`CF mechanism`, LogLevel.DEBUG)
|
|
827
|
+
|
|
828
|
+
const potStoragePath = getPotStorageFilePath(files.potFilename)
|
|
829
|
+
const firstZkeyStoragePath = getZkeyStorageFilePath(prefix, `${prefix}_${genesisZkeyIndex}.zkey`)
|
|
830
|
+
// Prepare temporary file paths.
|
|
831
|
+
// (nb. these are needed to download the necessary artifacts for verification from AWS S3).
|
|
832
|
+
verificationTranscriptTemporaryLocalPath = createTemporaryLocalPath(verificationTranscriptCompleteFilename)
|
|
833
|
+
const potTempFilePath = createTemporaryLocalPath(`${circuitId}_${participantDoc.id}.pot`)
|
|
834
|
+
const firstZkeyTempFilePath = createTemporaryLocalPath(`${circuitId}_${participantDoc.id}_genesis.zkey`)
|
|
835
|
+
const lastZkeyTempFilePath = createTemporaryLocalPath(`${circuitId}_${participantDoc.id}_last.zkey`)
|
|
836
|
+
|
|
837
|
+
// Create and populate transcript.
|
|
838
|
+
const transcriptLogger = createCustomLoggerForFile(verificationTranscriptTemporaryLocalPath)
|
|
839
|
+
transcriptLogger.info(
|
|
840
|
+
`${
|
|
841
|
+
isFinalizing ? `Final verification` : `Verification`
|
|
842
|
+
} transcript for ${prefix} circuit Phase 2 contribution.\n${
|
|
843
|
+
isFinalizing ? `Coordinator ` : `Contributor # ${Number(lastZkeyIndex)}`
|
|
844
|
+
} (${contributorOrCoordinatorIdentifier})\n`
|
|
845
|
+
)
|
|
823
846
|
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
// Step (1.A.4).
|
|
830
|
-
isContributionValid = await zKey.verifyFromInit(
|
|
831
|
-
firstZkeyTempFilePath,
|
|
832
|
-
potTempFilePath,
|
|
833
|
-
lastZkeyTempFilePath,
|
|
834
|
-
transcriptLogger
|
|
835
|
-
)
|
|
836
|
-
|
|
837
|
-
// Compute contribution hash.
|
|
838
|
-
lastZkeyBlake2bHash = await blake512FromPath(lastZkeyTempFilePath)
|
|
847
|
+
// Step (1.A.2).
|
|
848
|
+
await downloadArtifactFromS3Bucket(bucketName, potStoragePath, potTempFilePath)
|
|
849
|
+
await downloadArtifactFromS3Bucket(bucketName, firstZkeyStoragePath, firstZkeyTempFilePath)
|
|
850
|
+
await downloadArtifactFromS3Bucket(bucketName, lastZkeyStoragePath, lastZkeyTempFilePath)
|
|
839
851
|
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
printLog(`Error while unlinking temporary files - Error ${error}`, LogLevel.WARN)
|
|
848
|
-
}
|
|
852
|
+
// Step (1.A.4).
|
|
853
|
+
isContributionValid = await zKey.verifyFromInit(
|
|
854
|
+
firstZkeyTempFilePath,
|
|
855
|
+
potTempFilePath,
|
|
856
|
+
lastZkeyTempFilePath,
|
|
857
|
+
transcriptLogger
|
|
858
|
+
)
|
|
849
859
|
|
|
850
|
-
|
|
860
|
+
// Compute contribution hash.
|
|
861
|
+
lastZkeyBlake2bHash = await blake512FromPath(lastZkeyTempFilePath)
|
|
862
|
+
|
|
863
|
+
// Free resources by unlinking temporary folders.
|
|
864
|
+
// Do not free-up verification transcript path here.
|
|
865
|
+
try {
|
|
866
|
+
fs.unlinkSync(potTempFilePath)
|
|
867
|
+
fs.unlinkSync(firstZkeyTempFilePath)
|
|
868
|
+
fs.unlinkSync(lastZkeyTempFilePath)
|
|
869
|
+
} catch (error: any) {
|
|
870
|
+
printLog(`Error while unlinking temporary files - Error ${error}`, LogLevel.WARN)
|
|
851
871
|
}
|
|
872
|
+
|
|
873
|
+
await completeVerification()
|
|
852
874
|
}
|
|
853
875
|
}
|
|
854
876
|
)
|
|
@@ -859,9 +881,9 @@ export const verifycontribution = functionsV2.https.onCall(
|
|
|
859
881
|
* this does not happen if the participant is actually the coordinator who is finalizing the ceremony.
|
|
860
882
|
*/
|
|
861
883
|
export const refreshParticipantAfterContributionVerification = functionsV1
|
|
862
|
-
.region(
|
|
884
|
+
.region("europe-west1")
|
|
863
885
|
.runWith({
|
|
864
|
-
memory: "
|
|
886
|
+
memory: "1GB"
|
|
865
887
|
})
|
|
866
888
|
.firestore.document(
|
|
867
889
|
`/${commonTerms.collections.ceremonies.name}/{ceremony}/${commonTerms.collections.circuits.name}/{circuit}/${commonTerms.collections.contributions.name}/{contributions}`
|
|
@@ -942,9 +964,9 @@ export const refreshParticipantAfterContributionVerification = functionsV1
|
|
|
942
964
|
* and verification key extracted from the circuit final contribution (as part of the ceremony finalization process).
|
|
943
965
|
*/
|
|
944
966
|
export const finalizeCircuit = functionsV1
|
|
945
|
-
.region(
|
|
967
|
+
.region("europe-west1")
|
|
946
968
|
.runWith({
|
|
947
|
-
memory: "
|
|
969
|
+
memory: "1GB"
|
|
948
970
|
})
|
|
949
971
|
.https.onCall(async (data: FinalizeCircuitData, context: functionsV1.https.CallableContext) => {
|
|
950
972
|
if (!context.auth || !context.auth.token.coordinator) logAndThrowError(COMMON_ERRORS.CM_NOT_COORDINATOR_ROLE)
|
package/src/functions/index.ts
CHANGED
|
@@ -31,6 +31,8 @@ export {
|
|
|
31
31
|
generatePreSignedUrlsParts,
|
|
32
32
|
completeMultiPartUpload
|
|
33
33
|
} from "./storage"
|
|
34
|
+
export { bandadaValidateProof } from "./bandada"
|
|
35
|
+
export { checkNonceOfSIWEAddress } from "./siwe"
|
|
34
36
|
export { checkAndRemoveBlockingContributor, resumeContributionAfterTimeoutExpiration } from "./timeout"
|
|
35
37
|
|
|
36
38
|
admin.initializeApp()
|
|
@@ -44,9 +44,9 @@ dotenv.config()
|
|
|
44
44
|
* @dev true when the participant can participate (1.A, 3.B, 1.D); otherwise false.
|
|
45
45
|
*/
|
|
46
46
|
export const checkParticipantForCeremony = functions
|
|
47
|
-
.region(
|
|
47
|
+
.region("europe-west1")
|
|
48
48
|
.runWith({
|
|
49
|
-
memory: "
|
|
49
|
+
memory: "1GB"
|
|
50
50
|
})
|
|
51
51
|
.https.onCall(async (data: { ceremonyId: string }, context: functions.https.CallableContext) => {
|
|
52
52
|
if (!context.auth || (!context.auth.token.participant && !context.auth.token.coordinator))
|
|
@@ -134,7 +134,7 @@ export const checkParticipantForCeremony = functions
|
|
|
134
134
|
participantDoc.ref.update({
|
|
135
135
|
status: ParticipantStatus.EXHUMED,
|
|
136
136
|
contributions,
|
|
137
|
-
tempContributionData: tempContributionData
|
|
137
|
+
tempContributionData: tempContributionData || FieldValue.delete(),
|
|
138
138
|
contributionStep: ParticipantContributionStep.DOWNLOADING,
|
|
139
139
|
contributionStartedAt: 0,
|
|
140
140
|
verificationStartedAt: FieldValue.delete(),
|
|
@@ -175,9 +175,9 @@ export const checkParticipantForCeremony = functions
|
|
|
175
175
|
* 2) the participant has just finished the contribution for a circuit (contributionProgress != 0 && status = CONTRIBUTED && contributionStep = COMPLETED).
|
|
176
176
|
*/
|
|
177
177
|
export const progressToNextCircuitForContribution = functions
|
|
178
|
-
.region(
|
|
178
|
+
.region("europe-west1")
|
|
179
179
|
.runWith({
|
|
180
|
-
memory: "
|
|
180
|
+
memory: "1GB"
|
|
181
181
|
})
|
|
182
182
|
.https.onCall(async (data: { ceremonyId: string }, context: functions.https.CallableContext): Promise<void> => {
|
|
183
183
|
if (!context.auth || (!context.auth.token.participant && !context.auth.token.coordinator))
|
|
@@ -233,9 +233,9 @@ export const progressToNextCircuitForContribution = functions
|
|
|
233
233
|
* 5) Completed contribution computation and verification.
|
|
234
234
|
*/
|
|
235
235
|
export const progressToNextContributionStep = functions
|
|
236
|
-
.region(
|
|
236
|
+
.region("europe-west1")
|
|
237
237
|
.runWith({
|
|
238
|
-
memory: "
|
|
238
|
+
memory: "1GB"
|
|
239
239
|
})
|
|
240
240
|
.https.onCall(async (data: { ceremonyId: string }, context: functions.https.CallableContext) => {
|
|
241
241
|
if (!context.auth || (!context.auth.token.participant && !context.auth.token.coordinator))
|
|
@@ -296,9 +296,9 @@ export const progressToNextContributionStep = functions
|
|
|
296
296
|
* @dev enable the current contributor to resume a contribution from where it had left off.
|
|
297
297
|
*/
|
|
298
298
|
export const permanentlyStoreCurrentContributionTimeAndHash = functions
|
|
299
|
-
.region(
|
|
299
|
+
.region("europe-west1")
|
|
300
300
|
.runWith({
|
|
301
|
-
memory: "
|
|
301
|
+
memory: "1GB"
|
|
302
302
|
})
|
|
303
303
|
.https.onCall(
|
|
304
304
|
async (data: PermanentlyStoreCurrentContributionTimeAndHash, context: functions.https.CallableContext) => {
|
|
@@ -355,9 +355,9 @@ export const permanentlyStoreCurrentContributionTimeAndHash = functions
|
|
|
355
355
|
* @dev enable the current contributor to resume a multi-part upload from where it had left off.
|
|
356
356
|
*/
|
|
357
357
|
export const temporaryStoreCurrentContributionMultiPartUploadId = functions
|
|
358
|
-
.region(
|
|
358
|
+
.region("europe-west1")
|
|
359
359
|
.runWith({
|
|
360
|
-
memory: "
|
|
360
|
+
memory: "1GB"
|
|
361
361
|
})
|
|
362
362
|
.https.onCall(
|
|
363
363
|
async (data: TemporaryStoreCurrentContributionMultiPartUploadId, context: functions.https.CallableContext) => {
|
|
@@ -409,9 +409,9 @@ export const temporaryStoreCurrentContributionMultiPartUploadId = functions
|
|
|
409
409
|
* @dev enable the current contributor to resume a multi-part upload from where it had left off.
|
|
410
410
|
*/
|
|
411
411
|
export const temporaryStoreCurrentContributionUploadedChunkData = functions
|
|
412
|
-
.region(
|
|
412
|
+
.region("europe-west1")
|
|
413
413
|
.runWith({
|
|
414
|
-
memory: "
|
|
414
|
+
memory: "1GB"
|
|
415
415
|
})
|
|
416
416
|
.https.onCall(
|
|
417
417
|
async (data: TemporaryStoreCurrentContributionUploadedChunkData, context: functions.https.CallableContext) => {
|
|
@@ -469,9 +469,9 @@ export const temporaryStoreCurrentContributionUploadedChunkData = functions
|
|
|
469
469
|
* contributed to every selected ceremony circuits (= DONE).
|
|
470
470
|
*/
|
|
471
471
|
export const checkAndPrepareCoordinatorForFinalization = functions
|
|
472
|
-
.region(
|
|
472
|
+
.region("europe-west1")
|
|
473
473
|
.runWith({
|
|
474
|
-
memory: "
|
|
474
|
+
memory: "1GB"
|
|
475
475
|
})
|
|
476
476
|
.https.onCall(async (data: { ceremonyId: string }, context: functions.https.CallableContext): Promise<boolean> => {
|
|
477
477
|
if (!context.auth || !context.auth.token.coordinator) logAndThrowError(COMMON_ERRORS.CM_NOT_COORDINATOR_ROLE)
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import dotenv from "dotenv"
|
|
2
|
+
import fetch from "@adobe/node-fetch-retry"
|
|
3
|
+
import * as functions from "firebase-functions"
|
|
4
|
+
import { getAuth } from "firebase-admin/auth"
|
|
5
|
+
import admin from "firebase-admin"
|
|
6
|
+
import { Auth0UserInfo, CheckNonceOfSIWEAddressRequest, CheckNonceOfSIWEAddressResponse } from "../types"
|
|
7
|
+
import { setEthProvider } from "../lib/services"
|
|
8
|
+
|
|
9
|
+
dotenv.config()
|
|
10
|
+
|
|
11
|
+
export const checkNonceOfSIWEAddress = functions
|
|
12
|
+
.region("europe-west1")
|
|
13
|
+
.runWith({ memory: "1GB" })
|
|
14
|
+
.https.onCall(async (data: CheckNonceOfSIWEAddressRequest): Promise<CheckNonceOfSIWEAddressResponse> => {
|
|
15
|
+
try {
|
|
16
|
+
const { auth0Token } = data
|
|
17
|
+
const result = (await fetch(`${process.env.AUTH0_APPLICATION_URL}/userinfo`, {
|
|
18
|
+
method: "GET",
|
|
19
|
+
headers: {
|
|
20
|
+
"content-type": "application/json",
|
|
21
|
+
authorization: `Bearer ${auth0Token}`
|
|
22
|
+
}
|
|
23
|
+
}).then((_res) => _res.json())) as Auth0UserInfo
|
|
24
|
+
if (!result.sub) {
|
|
25
|
+
return {
|
|
26
|
+
valid: false,
|
|
27
|
+
message: "No user detected. Please check device flow token"
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
const auth = getAuth()
|
|
31
|
+
// check nonce
|
|
32
|
+
const parts = result.sub.split("|")
|
|
33
|
+
const address = decodeURIComponent(parts[2]).split(":")[2]
|
|
34
|
+
|
|
35
|
+
const minimumNonce = Number(process.env.ETH_MINIMUM_NONCE)
|
|
36
|
+
const nonceBlockHeight = "latest" // process.env.ETH_NONCE_BLOCK_HEIGHT
|
|
37
|
+
// look up nonce for address @block
|
|
38
|
+
let nonceOk = true
|
|
39
|
+
if (minimumNonce > 0) {
|
|
40
|
+
const provider = setEthProvider()
|
|
41
|
+
console.log(`got provider - block # ${await provider.getBlockNumber()}`)
|
|
42
|
+
const nonce = await provider.getTransactionCount(address, nonceBlockHeight)
|
|
43
|
+
console.log(`nonce ${nonce}`)
|
|
44
|
+
nonceOk = nonce >= minimumNonce
|
|
45
|
+
}
|
|
46
|
+
console.log(`checking nonce ${nonceOk}`)
|
|
47
|
+
if (!nonceOk) {
|
|
48
|
+
return {
|
|
49
|
+
valid: false,
|
|
50
|
+
message: "Eth address does not meet the nonce requirements"
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
try {
|
|
54
|
+
await admin.auth().createUser({
|
|
55
|
+
displayName: address,
|
|
56
|
+
uid: address
|
|
57
|
+
})
|
|
58
|
+
} catch (error: any) {
|
|
59
|
+
// if user already exist then just pass
|
|
60
|
+
if (error.code !== "auth/uid-already-exists") {
|
|
61
|
+
throw new Error(error)
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
const token = await auth.createCustomToken(address)
|
|
65
|
+
return {
|
|
66
|
+
valid: true,
|
|
67
|
+
token
|
|
68
|
+
}
|
|
69
|
+
} catch (error) {
|
|
70
|
+
return {
|
|
71
|
+
valid: false,
|
|
72
|
+
message: `Something went wrong ${error}`
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
export default checkNonceOfSIWEAddress
|
package/src/functions/storage.ts
CHANGED
|
@@ -134,7 +134,7 @@ const checkIfBucketIsDedicatedToCeremony = async (bucketName: string) => {
|
|
|
134
134
|
export const createBucket = functions
|
|
135
135
|
.region("europe-west1")
|
|
136
136
|
.runWith({
|
|
137
|
-
memory: "
|
|
137
|
+
memory: "1GB"
|
|
138
138
|
})
|
|
139
139
|
.https.onCall(async (data: CreateBucketData, context: functions.https.CallableContext) => {
|
|
140
140
|
// Check if the user has the coordinator claim.
|
|
@@ -193,8 +193,10 @@ export const createBucket = functions
|
|
|
193
193
|
CORSConfiguration: {
|
|
194
194
|
CORSRules: [
|
|
195
195
|
{
|
|
196
|
-
AllowedMethods: ["GET"],
|
|
197
|
-
AllowedOrigins: ["*"]
|
|
196
|
+
AllowedMethods: ["GET", "PUT"],
|
|
197
|
+
AllowedOrigins: ["*"],
|
|
198
|
+
ExposeHeaders: ["ETag", "Content-Length"],
|
|
199
|
+
AllowedHeaders: ["*"]
|
|
198
200
|
}
|
|
199
201
|
]
|
|
200
202
|
}
|
|
@@ -236,7 +238,7 @@ export const createBucket = functions
|
|
|
236
238
|
export const checkIfObjectExist = functions
|
|
237
239
|
.region("europe-west1")
|
|
238
240
|
.runWith({
|
|
239
|
-
memory: "
|
|
241
|
+
memory: "1GB"
|
|
240
242
|
})
|
|
241
243
|
.https.onCall(async (data: BucketAndObjectKeyData, context: functions.https.CallableContext): Promise<boolean> => {
|
|
242
244
|
// Check if the user has the coordinator claim.
|
|
@@ -292,7 +294,7 @@ export const checkIfObjectExist = functions
|
|
|
292
294
|
export const generateGetObjectPreSignedUrl = functions
|
|
293
295
|
.region("europe-west1")
|
|
294
296
|
.runWith({
|
|
295
|
-
memory: "
|
|
297
|
+
memory: "1GB"
|
|
296
298
|
})
|
|
297
299
|
.https.onCall(async (data: BucketAndObjectKeyData, context: functions.https.CallableContext): Promise<any> => {
|
|
298
300
|
if (!context.auth) logAndThrowError(COMMON_ERRORS.CM_NOT_AUTHENTICATED)
|
|
@@ -339,7 +341,7 @@ export const generateGetObjectPreSignedUrl = functions
|
|
|
339
341
|
export const startMultiPartUpload = functions
|
|
340
342
|
.region("europe-west1")
|
|
341
343
|
.runWith({
|
|
342
|
-
memory: "
|
|
344
|
+
memory: "2GB"
|
|
343
345
|
})
|
|
344
346
|
.https.onCall(async (data: StartMultiPartUploadData, context: functions.https.CallableContext): Promise<any> => {
|
|
345
347
|
if (!context.auth || (!context.auth.token.participant && !context.auth.token.coordinator))
|
|
@@ -407,7 +409,8 @@ export const startMultiPartUpload = functions
|
|
|
407
409
|
export const generatePreSignedUrlsParts = functions
|
|
408
410
|
.region("europe-west1")
|
|
409
411
|
.runWith({
|
|
410
|
-
memory: "
|
|
412
|
+
memory: "1GB",
|
|
413
|
+
timeoutSeconds: 300
|
|
411
414
|
})
|
|
412
415
|
.https.onCall(
|
|
413
416
|
async (
|
|
@@ -484,7 +487,7 @@ export const generatePreSignedUrlsParts = functions
|
|
|
484
487
|
export const completeMultiPartUpload = functions
|
|
485
488
|
.region("europe-west1")
|
|
486
489
|
.runWith({
|
|
487
|
-
memory: "
|
|
490
|
+
memory: "2GB"
|
|
488
491
|
})
|
|
489
492
|
.https.onCall(async (data: CompleteMultiPartUploadData, context: functions.https.CallableContext): Promise<any> => {
|
|
490
493
|
if (!context.auth || (!context.auth.token.participant && !context.auth.token.coordinator))
|