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